@TheToolBox對你有一個很好的答案。
只是爲了好玩,我將向您展示一種替代技術,使用發電機從coroutines獲得靈感。
Promise.prototype.bind = Promise.prototype.then;
const coro = g => {
const next = x => {
let {done, value} = g.next(x);
return done ? value : value.bind(next);
}
return next();
}
利用這一點,你的代碼將看起來像這樣
const addElement = elementText =>
new Promise(resolve => {
setTimeout(() => {
var element = document.createElement('H1');
element.innerText = `${elementText} ${Date.now()}`;
document.body.appendChild(element);
resolve();
}, Math.random() * 2000);
});
coro(function*() {
yield addElement('first');
yield addElement('second');
yield addElement('third');
yield addElement('fourth');
}());
有一些很有趣的東西,你可以使用發電機,承諾做。它們在這裏並不是立即可見的,因爲您的承諾不能解決任何實際值。
如果你真的resolve
一些值,你可以不喜歡
// sync
const appendChild = (x,y) => x.appendChild(y);
// sync
const createH1 = text => {
var elem = document.createElement('h1');
elem.innerText = `${text} ${Date.now()}`;
return elem;
};
// async
const delay = f =>
new Promise(resolve => {
setTimeout(() => resolve(f()), Math.random() * 2000);
});
// create generator; this time it has a name and accepts an argument
// mix and match sync/async as needed
function* renderHeadings(target) {
appendChild(target, yield delay(() => createH1('first')));
appendChild(target, yield delay(() => createH1('second')));
appendChild(target, yield delay(() => createH1('third')));
appendChild(target, yield delay(() => createH1('fourth')));
}
// run the generator; set target to document.body
coro(renderHeadings(document.body));
值得注意createH1
和appendChild
是同步的功能。這種方法有效地允許你將正常功能鏈接在一起,模糊同步和異步之間的界限。它也執行/行爲完全像您最初發布的代碼。
所以是的,這最後一個代碼示例可能會稍微有趣。
最後,
一個明顯的優點協程有過.then
鏈,是所有解決承諾可以在同一範圍內進行訪問。
比較.then
鏈...
op1()
.then(x => op2(x))
.then(y => op3(y)) // cannot read x here
.then(z => lastOp(z)) // cannot read x or y here
到協程...
function*() {
let x = yield op1(); // can read x
let y = yield op2(); // can read x and y here
let z = yield op3(); // can read x, y, and z here
lastOp([x,y,z]); // use all 3 values !
}
當然也有workarounds此使用的承諾,但是男孩哦它得到醜陋快...
如果您有興趣以這種方式使用發電機,我強烈建議您結賬co項目。
而這裏有一篇文章,Callbacks vs Coroutines,來自的創建者co,@tj。
無論如何,我希望你有樂趣學習一些其他技術^__^
您的箭頭功能可以簡化 - '。於是(X =>的addElement(「第二」))' - 同樣,你可以使用箭頭功能'addElement' - 但我不知道爲什麼你認爲你正在創建「大量新的關閉」 –
我也遇到了這個問題,並最終使用'bind'來代替,儘管它感覺就像凌亂(但避免了額外的函數包裝):'.then( addElement.bind(null,「second」))'等等。 –
想知道是否有在這裏創建的冗餘承諾對象。如果你有3個就足夠了,就像你創造6個承諾對象一樣?那麼已經創建了一個你不能重複使用的Promise對象?讓我想想我可能是錯的。 – Nishant