搜尋

首頁  >  問答  >  主體

非同步函數傳回的是 Promise,而不是值

我試著去了解 async/await 如何與 Promise 結合使用。

async function latestTime() {
  const bl = await web3.eth.getBlock('latest');
  console.log(bl.timestamp); // Returns a primitive
  console.log(typeof bl.timestamp.then == 'function'); //Returns false - not a promise
  return bl.timestamp;
}
const time = latestTime(); // Promise { <pending> }

據我了解,await 應該是阻塞的,並且在上面的程式碼中,它似乎阻止使用原語 timestamp 返回物件 bl 。然後,我的函數傳回原始值,但是時間變數設定為待處理的承諾而不是該原始值。我錯過了什麼?

P粉464208937P粉464208937496 天前584

全部回覆(2)我來回復

  • P粉099985373

    P粉0999853732023-10-20 14:57:49

    非同步前綴是 Promises 的一種包裝器。

    async function latestTime() {
        const bl = await web3.eth.getBlock('latest');
        console.log(bl.timestamp); // Returns a primitive
        console.log(typeof bl.timestamp.then == 'function'); //Returns false - not a promise
        return bl.timestamp;
    }

    與相同

    function latestTime() {
        return new Promise(function(resolve,success){
            const bl = web3.eth.getBlock('latest');
            bl.then(function(result){
                console.log(result.timestamp); // Returns a primitive
                console.log(typeof result.timestamp.then == 'function'); //Returns false - not a promise
                resolve(result.timestamp)
            })
    }

    回覆
    0
  • P粉002023326

    P粉0020233262023-10-20 12:58:06

    async 函數總是傳回一個 Promise。這就是它報告非同步工作完成情況的方式。如果您在另一個async函數中使用它,則可以使用await來等待其promise解決,但在非async中函數(通常在頂層或在事件處理程序中),您必須直接使用Promise,例如:

    latestTime()
    .then(time => {
        console.log(time);
    })
    .catch(error => {
        // Handle/report error
    });
    

    ...不過,如果您在 JavaScript 模組的頂層執行此操作,則所有現代環境現在都支援 模組中的頂層 await

    const time = await latestTime();

    (請注意,如果該Promise 被拒絕,您的模組將無法載入。如果即使Promise 失敗您的模組也能有意義地工作,請務必將其包裝在try/catch 中 處理承諾拒絕。)


    可能(或可能不會)以明確承諾回呼術語的形式揭示了一些事情,讓我們了解JavaScript 引擎如何在幕後處理您的async 函數:

    function latestTime() {
        return new Promise((resolve, reject) => {
            web3.eth.getBlock('latest')
            .then(bl => {
                console.log(bl.timestamp);
                console.log(typeof bl.timestamp.then == 'function');
                resolve(bl.timestamp);
            })
            .catch(reject);
        });
    }
    

    一些重要的說明:

    • 您傳遞給 new Promise 的函數(promise 執行器函數)由 new Promise 同步呼叫。
      • 這就是操作開始的原因,同步呼叫web3.eth.getBlock來開始工作。
    • Promise 執行器中拋出的任何錯誤(等)都會被 new Promise 捕獲並轉換為 Promise 拒絕。
    • 在 Promise 回呼中拋出的任何錯誤(例如我們傳遞的 then 錯誤)都會被捕獲並轉換為拒絕。

    回覆
    0
  • 取消回覆