2017-05-26 44 views
2

我有以下代碼:承諾爲基礎的功能迴路不運行異步

function asyncLoop() { 
    return new Promise(function(res, rej) { 
     for(let i=0;i<=400000000;i++) { 
      if(i===400000000) {console.log("done"); res();} 
     } 
    }); 
} 

asyncLoop().then(()=>{console.log("then")}); 
console.log("out"); 

我得到以下輸出:

done 
out 
then 

據我承諾的理解,asyncLoop應該異步運行及以下應該是輸出:

out 
done 
then 

什麼我錯過了嗎?

+0

https://stackoverflow.com/a/5436869/1278540然後VS做 –

+1

@DebajyotiDas這是關於jQuery的承諾 - 這使用本機。 – Jamiec

+0

Promise沒有「魔術」屬性來創建一些尚未異步的異步事件。它們只是一個標準化的通知和錯誤處理方案 - 僅此而已。如果底層操作不是異步的,那麼將其包裝在承諾中不會以某種方式使其變爲異步。 – jfriend00

回答

3

您的循環位於您傳遞給new Promise的回調中。該功能被稱爲「執行人」:

function executor(resolve, reject) 

執行人由new Promise稱爲同步。執行者的角色是設置任何異步事件以便最終調用resolvereject

見MDN:Promise constructor parameters

此功能與解析功能作爲它的兩個參數立即調用。

構造函數不會返回,直到執行完成

2

你做出了錯誤的假設。 Promise並不意味着是異步的,它們被用在異步的上下文中,以更簡單的方式來處理這些調用。要使某種過程「異步」,您可以使用setTimeout()

function asyncLoop() { 
    return new Promise(function(res, rej) { 
     setTimeout(function() { 
      for(let i=0;i<=400000000;i++) { 
       if(i===400000000) {console.log("done"); res();} 
      } 
     }, 0); 
    }); 
} 

asyncLoop().then(()=>{console.log("then")}); 
console.log("out"); 
+1

JavaScript是單線程的,這會阻止主瀏覽器線程,與原始問題一樣多,只能在事件循環的下一次運行中使用。 – jib

+0

事實上@jib,你是對的。這不是真的異步,只是延遲。 – Booster2ooo

1

允諾僅僅是一個返回值一個附加的回調而不是傳遞的回調函數,有幾個好處的約定。有關更多信息,請參閱MDN上的Using promises

JavaScript是單線程的事件循環。 .thensetTimeout時間表事件。

所有的JavaScript運行在瀏覽器的主線程,除非創建worker

function asyncLoop() { 
 
    for (let i = 0; i <= 400000000; i++) { 
 
    if (i == 400000000) { 
 
     self.postMessage('done'); 
 
    } 
 
    } 
 
} 
 

 
var blob = new Blob(["onmessage = " + asyncLoop.toString()], 
 
        {type: "text/javascript"}); 
 

 
var worker = new Worker(window.URL.createObjectURL(blob)); 
 

 
worker.onmessage = e => console.log(e.data); 
 
worker.postMessage("start");

+0

感謝您在Web Workers上的分享!現在探索。 – delfuego17