iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
1
Modern Web

30天入門JavaScript系列 第 29

【Day 29】Promise

  • 分享至 

  • twitterImage
  •  



實際上的最後一篇學習筆記,明天是使用的學習資源推薦跟個人反省會



Promise(承諾 或是約定)是ES6新增的一個物件

再開始講Promise(前先用簡單的比喻形容一下callback跟Promise的差別

假如今天想要花錢叫個漢堡外送

callback就是你打電話過去麥O勞,
跟他說一句我想要一個大O克餐,做好後到我家門口按電鈴再跟我收200元然後就掛了電話。
如果沒甚麼問題的話,會收到一份大O克並付200元。


但有可能出了問題,他送了一個麥O雞餐過來拿走你的200元,
或著出現五個外送員拿著五個大O克餐各跟你收200,
或著再也沒有回應了,你不知道大O克餐到底會不會來。


Promise的話就是你用UbOrEOt叫了一份大O克餐並使用現金付款,
叫完後他會給你一筆訂單確定你成功下單了。

你可以看到這筆訂單就去做其他事,順便想著等等有人來按門鈴的話就去開門付錢,
或是UbOrEOt通知大O克賣完了只能取消,
又或著超過半小時沒來的話手動取消訂單,自己出門去買消夜。


callback基本上是把控制權交給外部,而Promise則是依照外部的結果來處理接下來的動作

...廢話講多了 還是來寫程式吧


先建立一個Promise物件印出來看看

const Psample = new Promise((resolve, reject) => {
});
console.log(Psample);


建立一個Promise,要傳入兩個函式(resolve跟reject,不需要我們宣告)當參數,
如果這個Promise成功實現了,則呼叫resolve函式,當失敗或出現錯誤時會呼叫reject

接著來看印出來的結果

https://ithelp.ithome.com.tw/upload/images/20200929/20129836UtUEjqz7GJ.png

會看到Promise有兩個屬性

首先是[[PromiseState]],這個代表承諾目前的狀態,狀態有三種情況


pending(未定):代表承諾還在處理中
fulfilled(達成):resolve被呼叫,代表承諾達成了
rejected(否決):reject被呼叫,代表承諾被否決了


目前上面的Promise沒有任何呼叫resolve或reject的內容,所以目前的狀態為pending

const Psample = new Promise((resolve, reject) => {
  resolve();
});
console.log(Psample);


不做甚麼事直接呼叫resolve,會看到[[PromiseState]]變為fulfilled(已達成)
https://ithelp.ithome.com.tw/upload/images/20200929/20129836behaD8lXTQ.png


另外Promise的狀態一但達成或被否決,狀態就不會再被改變了
像這個樣子

const Psample = new Promise((resolve, reject) => {
  reject(); //先否決
  resolve(); //再達成
});
console.log(Psample);


https://ithelp.ithome.com.tw/upload/images/20200929/20129836sHYSaeYiqE.png
變為rejected後就不會再更動了


另一個值為[[PromiseResult]],這個是承諾的結果值,會在呼叫resolve或reject當作參數接收

const Psample = new Promise((resolve, reject) => {
  resolve('結果值');
});
console.log(Psample);


https://ithelp.ithome.com.tw/upload/images/20200929/201298367ik1hAtCBo.png
會看到[[PromiseResult]]的內容變為結果值


then()方法


當Promise有結果後,傳入then()方法回呼函式會自動被觸發,
如果有[[PromiseResult]]的結果會被當作參數傳入回呼函式

語法
Promise.then(成功時回呼的函式,失敗時呼叫的函式)


這樣解釋起來還是很難懂,還是用範例

function makeAPromise() { //一個回傳Promise的函式
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const random = Math.random();
      if (random > 0.5) {
        resolve(random);//成功
      } else {
        reject(random);//失敗
      }
    }, 1000);
  });
}

makeAPromise().then( //呼叫函式建立Promise
  (value) => {//成功的話會呼叫這裡
    console.log('大於0.5?,你的數字' + value);
  },
  (value) => {//失敗的話會呼叫這裡
    console.log('小於0.5?,你的數字' + value);
  }
);


makeAPromise()這個函式會建立一個Promise,會在一秒後隨機個0~1的數字,
再以這個隨機數來決定這個Promise是達成還是被否決,再依結果值行then()內的回呼

https://ithelp.ithome.com.tw/upload/images/20200929/20129836KyyRFSA6V9.png
上面結果會在一秒後印出


then()的串接


then()方法可以只傳入一個函式(成功時回呼),
回呼如果有return一般值時,會自動回傳一個新的Promise(自動成功)跟值,

代表可以在後面直接加上then()來處理新的Promise成功要做的回呼,
並且能接收return值當作參數來使用

以下是用then的串接來模擬鐵人賽想題目->找資料->寫文->完成的一步一步動作

function makeAPromise() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const random = Math.random();
      if (random > 0.1) {
        resolve();
      } else {
        reject();
      }
    }, 1000);
  });
}
makeAPromise()
  .then(() => {
    console.log('想好題目了');
    return 'Promise';
  })
  .then((v) => {
    console.log('開始找參考');
    return { theme: v, data: '相關資料' };
  })
  .then((v) => {
    console.log('開始寫文');
    return { theme: v.theme, data: v.data, article: '(文章內容)' };
  })
  .then((v) => {
    console.log(
      `寫好了! 題目為:${v.theme} 內容:${v.article} 參考資料:${v.data} 可以發文了`
    );
  })

上一篇
【Day 28】callback hell跟callback問題
下一篇
【Day 30】前端學習資源推薦 &30天反省
系列文
30天入門JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言