簡體   English   中英

JS 中的異步/等待混淆

[英]Async/Await confusion in JS

我在 JS 中學習異步並遇到了 Async/Await。 然后,我遇到了這段代碼:

function scaryClown() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 2000);
  });
}

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

msg(); // Message: 🤡 <-- after 2 seconds

因此,我對上面的代碼有疑問。 首先,如果函數本身只返回未定義的 Promise,即函數沒有明確使用 return 關鍵字,那么異步函數 msg() 如何返回消息值。 其次,await 是否返回 Promise 或 value 本身已經從 Promise 解包?

function scaryClown() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 2000);
  });
}

上面的函數是一個在調用時返回一個promise的函數,但只會在2秒后被解析。

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

上面的函數是異步函數,它等待承諾得到解決(在你的情況下,2 秒后),然后只有 console.log() 觸發。

注意:函數 msg() 下的任何代碼行都會被執行,而不管 promise 和異步函數如何。

運行代碼片段

 function scaryClown() { return new Promise(resolve => { setTimeout(() => { resolve('🤡'); }, 2000); }); } async function msg() { console.log(scaryClown()); // try without await, so it will not wait for the result and prints first, but an unresolved promise const msg = await scaryClown(); // actual result which is resolved, because we awaited console.log('Message:', msg); // Prints once the resolved value is available. } msg(); //executes first but only prints the value once it is resolved. console.log('I will continue executing irrespective of async func msg()');

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

await 解析 promise 並返回解析值。 所以上面的代碼可以像下面這樣寫。 希望這能讓你理解異步等待。

function msg() {
  scaryClown().then(msg => {
    console.log('Message:', msg);
  });    
}

這是發生的事情:

async函數(即msg )被調用時,它會創建一個 promise 對象(我們稱之為 P),它會在處理await表達式時返回。 scaryClown()執行,它設置計時器並返回另一個承諾對象; 讓我們稱它為 Q。然后await被處理:在那個時刻函數返回承諾 P。這個承諾在那一刻沒有被解決; 它正在等待中。

如果在msg()調用之后還有任何其他代碼,那么它的執行就像在任何函數調用之后的情況一樣。 繼續執行直到調用堆棧為空。

然后,一段時間后,由scaryClown()安排的計時器事件將觸發,相應的承諾 Q 將解析。 因為這個promise Q 在await表達式中,這個解析觸發了msg()的執行上下文的恢復,其中await表達式現在被評估為Q 的解析值,即“🤡”。

變量msg獲得分配的這個值,並與console.log顯示。 然后函數完成,在這種特殊情況下沒有任何顯式return 請記住,該函數已經返回了,所以這不是一個真正的正常返回:代碼執行真正到此結束,因為調用堆棧上沒有任何內容。 這使得承諾 P 解決。 如果有一個顯式的return語句,帶有一個值,promise P 就會用那個值解析。 但是由於您的示例中沒有這樣的return語句,promise P 用undefined解析。

由於您沒有對msg()返回的值執行任何操作,因此您實際上看不到它返回的內容。 如果你會這樣做:

msg().then(console.log);

...您會在控制台中看到undefined

你的問題:

如果函數本身只返回未定義的 Promise,即函數沒有明確使用return關鍵字,那么async function msg()如何返回消息值。

msg()調用當前為您提供消息值。 相反,它使用console.log輸出它,但這不是msg()返回的值。 返回的值是一個承諾。 即使它有一個明確的return關鍵字,它仍然不會讓msg()返回一個承諾以外的東西。 唯一的區別是承諾最終會解析為什么

await返回 Promise 或 value 本身已經從 Promise 解包?

await在兩個不同的時刻做兩件事。 首先它使函數返回給調用者。 然后,當它等待的承諾解決時,它使函數再次繼續運行,並且await代表當時承諾的,因此可以將其分配給變量(或以其他方式使用)。

我個人在談論承諾時不使用動詞“解開”。 但是是的,表達式await promise計算(異步)到promise實現的值。

暫無
暫無

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

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