2016-02-03 57 views
2

下面的代碼掛在Firefox和Chrome,但不是在邊緣:是promise.then異步或不?

let sequence = Promise.resolve(); 
function fire() { 
    sequence.then(fire) 
}; 
fire(); 

我認爲它沒有在Firefox掛了幾個版本前,我很困惑。這裏的正確行爲是什麼?

編輯:邊緣37.14316現在掛起。

+0

什麼是預期行爲,結果? – guest271314

+0

可能只是一個自動武器開火永遠 – maksymiuk

+0

順便說一句,你的意思是'序列= sequence.then(火)'? – Bergi

回答

1

它掛起,因爲.then鏈在微任務隊列上執行,不像例如。 setTimeout其執行主JavaScript事件隊列:

let sequence = Promise.resolve(); 
function fire() { 
    setTimeout(fire); // doesn't hang 
}; 
fire(); 

大多數瀏覽器清空microtask隊列中完全處於當前運行至完成的尾巴,你的代碼阻止它曾經排空,拖延主要JavaScript事件隊列。

瀏覽器並未完全掛起,因爲用戶可能會在一段時間後停止此失控腳本。瀏覽器在此期間的感覺如何,取決於瀏覽器是否支持多個進程。例如。由於開發版使用多個進程,所以Firefox開發者版在這裏的表現要好於Firefox。

4

是,Promise.then是異步,但是當你解決的承諾向右走,然後繼續調用回調內部相同的功能,你會得到一個無限循環,並在瀏覽器掛起

簡單來說,你」重新做

function fire() { 
    fire(); // goes on forever 
} 
fire(); 

唯一的區別是fire是一個已經解決了異步回調,以及火災的時候了。

如果Edge沒有掛起,那只是因爲它可以更好地處理遞歸。

enter image description here

+0

是的,它會無限期地調用'fire',但它不應該掛起,如果承諾回調異步運行。我的意思是,它應該是'火 - >(一點時間) - >火 - >(一點時間) - >火 - >(...無限循環)'。 –

+0

@KagamiSaschaRosylight:就是這樣,只有「*一點點時間*」非常非常短。其他任何運行都太短。 – Bergi

+0

但是什麼時候,承諾解決了,沒有什麼可以等待的?最好的情況是,瀏覽器檢查隊列,它是空的,並在幾秒內再次觸發'fire' – adeneo

1

正確的做法是掛。你不會得到堆棧溢出,但異步無限遞歸仍然是無限遞歸。

1:這是microtask隊列中的一個無限循環。其他承諾工作可能會運行,但沒有其他的。