2016-06-22 29 views
3

通過在OpenUI5 code-base我碰到這個片段:Promise.resolve不帶參數的

// Wait until everything is rendered (parent height!) before reading/updating sizes. 
// Use a promise to make sure 
// to be executed before timeouts may be executed. 
Promise.resolve().then(this._updateTableSizes.bind(this, true)); 

它看起來像native Promise function正在被使用,不帶參數傳遞給它的resolve函數,它接受一個:

由此承諾解決的論點。也可以是承諾或 可以解決。

所以,因爲它看起來像承諾只會立即解決,並調用then的回調,或許意圖是similar to

var self = this; 
setTimeout(function() { 
    self._updateTableSizes.bind(self, true) 
}, 0); 

...基本上,釋放的JavaScript運行 - 實時事件循環來完成其他事情(如渲染),然後回到回調?

我的問題是:

這是一個常見的模式?最佳實踐?這兩種方法都有什麼優點/缺點?

+1

我不知道答案,但我覺得你的猜測是正確的,即使用一個立即解決的承諾僅僅是如你所說,一個聰明的用法可以立即執行更新而不會超時。我不知道這種情況的最佳做法,但我經常使用'Promise.resolve()。then(...)'來確保捕獲在承諾鏈中使用的同步代碼中引發的錯誤,所以我不要認爲這是一個不好的選擇。 –

+0

「等到所有東西都呈現」 - 如果這意味着根據瀏覽器觀察樣式變化進行渲染,Promise.resolve()。then(...)'是不夠的。據我所知,沒有辦法讓一個函數在渲染之後而在下一個任務之前運行。 –

回答

5

是的,Promise.resolve()會立即滿足您隱式傳入的undefined值。回調仍然是異步執行 - 就像您發佈的setTimeout片段中一樣。

然而,在代碼中的註釋說明,其目的是不僅僅是執行異步回調:

使用的承諾,以確保可以執行超時之前執行。

承諾回調在超時或其他事件之前運行,這些細微的時間差異有時很重要。鑑於任務循環的選擇通常並不重要,否則這不是一種常見模式;但它是一種有效的模式,當你需要時,它就是你需要的。

+1

對我來說,做這件事的另一個原因是結果是「then-able」,所以它爲我打算在後期開發的異步函數提供了一個很好的存根,例如'function codeMeLater(){return Promise.resolve(「some day ,我會計算這個「); }' – danh

+0

@danh:哦,當然'Promise.resolve'是一個非常有用的函數,我只是提到具體的模式和回調,當我說它不常見時。 – Bergi

+0

這是否意味着ES6'Promise' API實現了一個微任務機制[如此處所述](http://stackoverflow.com/a/25933985/6445533)。據我瞭解,微任務可能導致例如與遞歸有關的阻塞UI。 – ftor

1

我注意到這個填充工具的技術:https://github.com/wicg/inert(含評論)

const newButton = document.createElement('button'); 
const inertContainer = document.querySelector('[inert]'); 
inertContainer.appendChild(newButton); 
// Wait for the next microtask to allow mutation observers to react to the DOM change 
Promise.resolve().then(() => { 
expect(isUnfocusable(newButton)).to.equal(true); 
});