Promise chain 鏈| 為什麼會有兩次then?

在看MDN fetch文件時,

https://developer.mozilla.org/zh-TW/docs/Web/API/Fetch_API/Using_Fetch#使用_fetch_發送請求_request

看到以下code:

javascript

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

想說奇怪,在工作上都是接一個then,沒看過接兩個的。

研究一下,這與Javascript ES6 fetch函數有關。

第一個then代入的resolve函數有return response.json(),而response.json()返回一個Promise,這個Promise的executor做的是把傳輸資料解析成JSON,代表轉化成JSON的過程為一個非同步操作,所以可以再調用then,使用已經成功轉化成JSON的資料做處理。

因為工作上只用過axios套件,axios只需一次then就能取用JSON資料,這也是axios方便的地方。

回傳一個Promise物件,接收兩參數,Promise成功和失敗的回調函數(handler)。

javascript

p.then(onFulfilled[, onRejected]);

p.then(function(value) {
  // fulfillment
}, function(reason) {
  // rejection
});

回傳一個Promise,它的狀態是根據handler回傳的值:

  1. 回傳一個值,則 then 回傳一個 已實現(resolved)的promise
  2. 拋出一個例外,則 then 回傳一個 已拒絕(rejected)的promise
  3. 回傳一個已實現的Promise,則 then 回傳一個 已實現(resolved)的promise
  4. 回傳一個已拒絕的Promise,則 then 回傳一個 已拒絕(resolved)的promise
  5. 回傳一個擱置(pending)的Promise,則 then 回傳一個Promise,成功與否由隨後的handler決定,如上面的範例
  6. 沒有回傳值,則 then 回傳一個已實現(resolved)的Promise,但Promise的value(property)是undefined

最後一點,MDN沒有,自己測的,用Chrome印出的console如下:

  1. 因為then會回傳Promise,所以才有Promise鏈的發生(第五點)

  2. 我自己開發handler沒有回傳過Promise,通常都沒有回傳東西,因為不需要對拿到的值做非同步處理。

  3. 第三、四點還有一點疑問,要怎麼寫回傳已實現或拒絕的Promise? 例如: return P1 P1是一個已實現的Promise

  4. MDN文件中這個code可以自己去跑看看

    javascript

    var resolvedProm = Promise.resolve(33);
    
    var thenProm = resolvedProm.then(function(value){
        console.log("我在 main stack 之後被呼叫。收到及將回傳的值為:" + value);
        return value;  // 可以試看看不要return 東西(第六點)
    });
    // 立即紀錄 thenProm
    console.log(thenProm);
    
    // 我們可以使用 setTimeout 以延遲(postpone)函式執行直到堆疊為空
    setTimeout(function(){
        console.log(thenProm);
    });

上述第三點,Promise有內建方法可以回傳已實現的Promise

**Promise.resolve**

javascript

Promise.resolve('Success').then(function(value) {
  console.log(value); // "Success"
}, function(value) {
  // not called
});

如果要回傳rejected狀態的Promsie

Promise.reject()

所以在then所回調的函數裡面,可以這樣寫

return Promise.resolve("Success")

https://blog.csdn.net/xiaoyuer_2020/article/details/112309991

https://developer.mozilla.org/en-US/docs/Web/API/Response/json

https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve