簡體   English   中英

promise.then 機制如何工作?

[英]How the promise.then mechanisem works?

觀看視頻並閱讀 [Promise.then][1] 后,我仍然不明白它是如何工作的。 所以我寫了一個例子,並打印到控制台,但仍然使用 output 我無法理解它是如何工作的。 我希望我的問題足夠清楚,如果沒有,請告訴我,我會根據您的回答嘗試詳細說明。 這是我的代碼:

   const getCountryData = function (country) {

   fetch(`https://restcountries.eu/rest/v2/name/${country}`)
     .then(response => {
       console.log('111111111111111');
       if (!response.ok)
         throw new Error(`Country not found (${response.status})`);
       return response.json();
       })
     .then(data => {
         console.log('22222222222');
        const neighbour = data[0].borders[0];
       if (!neighbour) return;
       return fetch(`https://restcountries.eu/rest/v2/alpha/${neighbour}`);
     })
     .then(response => {
         console.log('333333333')
       if (!response.ok)
         throw new Error(`Country not found (${response.status})`);
       return response.json();
        })
     .then(data => console.log('44444444444'))
     .catch(err => {
       console.error(`${err} 💥💥💥`);
     })
     .finally(() => {
       console.log('finalyyyy')
     });
     
     console.log("after all async calls");
 };

我無法理解以下內容:

  1. 如果我們看第一個then的例子,它得到一個回調作為參數,回調返回一個Promise object。 那么哪個 object 調用第二個呢? 是從第一次調用返回的,還是從回調中返回的?
  2. 我知道回調“附加”到獲取 function。 例如,當獲取 function 將完成時,將執行回調。 我不明白如何以及何時調用第二個、第三個和第四個。 第一個回調還包含一個異步 function ** response.json()**,那么如果他需要json.response從第一個什么時候開始,那么第二個什么時候開始?
  3. 如果第一次或第二次發生異常,代碼究竟是如何知道跳轉到捕捉function 的?
    [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

then函數不接收回調,它們接收上一個異步操作的結果。 所以fetch的結果被傳遞給第一個thenresponse.json()的結果被傳遞給第二個then等等......

萬一出現錯誤,鏈條會斷裂,它會直接到達第一個catch function。

在幕后還有更多,考慮到then函數中的 fetch 和其他操作可以是異步的,所以在運行時發生的是 fetch function 的結果被推送到事件隊列中,當事件循環采取你的下一個然后從隊列中提取 function 並傳遞給 function。
本文解釋了它是如何在內部工作的: https://www.digitalocean.com/community/tutorials/understanding-the-event-loop-callbacks-promises-and-async-await-in-javascript

我將嘗試使用async/await運算符以不同的方式解釋這一點。

你的getCountryData function 的等價物如下

const getCountryData = async (country) => {
    console.log("after all async calls"); // explanation for the this line below
    try {
        let response1 = await fetch(`https://restcountries.eu/rest/v2/name/${country}`);

        // first then
        console.log('111111111111111');
        if (!response1.ok)
            throw new Error(`Country not found (${response1.status})`);
        let data1 = await response1.json();

        // second then
        console.log('22222222222');
        const neighbour = data1[0].borders[0];
        let response2;
        if (neighbour)
            response2 = await fetch(`https://restcountries.eu/rest/v2/alpha/${neighbour}`);

        // third then
        console.log('333333333');
        if (!response2.ok)
            throw new Error(`Country not found (${response2.status})`);
        let data2 = await response2.json();

        // fourth then
        console.log('44444444444');
    } catch (err) {
        console.error(`${err} 💥💥💥`);
    } finally {
        console.log('finalyyyy');
    }
}

首先,你會看到你最后一行 function 中的console.log變成了我的 function 的第一行。 這是因為該行在異步 function fetch完成之前執行。

如您所見, fetch的最后一個返回變量在第一個then中可用,而then then可用。

  1. 那么對於你的第一個問題, then誰調用回調 function 呢? 顯然,您可以從 function 的async/await等效項中看到,它是按順序執行的。 前一個then的返回結果將是下一個then的參數。 因此,在第二個then中,當您return; ,它不會停止執行第三個then ,而是第三個then將接收undefined作為response參數。

  2. 如對問題 1 的回答所述,只要沒有未處理的錯誤或拒絕 promise,則then函數會自動按順序執行。 但是,對於第二個/第三個/第四個then回調 function 從第一個then訪問參數,不可能直接訪問,除非您將它與后續then的每個 return 一起傳遞。 這可以通過使用 then async/await運算符而不是then輕松實現。

  3. 當拋出錯誤時,代碼究竟是如何知道跳轉到 catch function 的? 在異步 function 中,拋出錯誤幾乎等同於拒絕 promise。 這樣想,每個then回調都包裝在一個try/catch塊中,該塊將調用catch中的 function 。

編輯:如果您執行fetch().then().then().catch() ,所有錯誤或被拒絕的承諾都將在 catch function 中處理。 但是如果你執行fetch().catch().then().then() ,只有錯誤或被拒絕的fetch將在 catch function 中處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM