例えば、サーバー上のリソースをajaxで引っ張ってきて、その結果をビューに反映するようなコードを書いたとします。雑に書くと以下の様な感じで。
fetch('/api/items/1').then(render);
fetch('/api/items/2').then(render);
/api/items/1
、 /api/items/2
はどちらが先に返ってくるかは保証されないですね。後のほうが先に返ってくると、多分想定とは違う結果になるかと思います。
そこで、実行回数をカウントしておいて、resolvedになったとき記録しておいたカウント数と比較して一致したときは最後に実行したものなのでそのまま後ろに流す、違ったらrejectするという層を作ります。
var latest = (() => {
var ids = {};
return key => {
ids[key] = ids[key] || 0;
var id = ++ids[key];
return x => id === ids[key] ? x : Promise.reject(new Error('old promise!'));
};
})();
これで並列に最後に実行した非同期処理のなかで最後に実行したやつだけresolvedになります、めでたし。
var sleep = t => new Promise(resolve => setTimeout(() => resolve(t), t));
var log = console.log.bind(console);
var error = console.error.bind(console);
sleep(100).then(latest('a')).then(log, error);
sleep(200).then(latest('a')).then(log, error);
sleep(300).then(latest('a')).then(log, error);
sleep(150).then(latest('a')).then(log, error); // resolved
sleep(340).then(latest('b')).then(log, error);
sleep(120).then(latest('b')).then(log, error);
sleep(110).then(latest('b')).then(log, error);
sleep(200).then(latest('b')).then(log, error); // resolved