この質問 に似ていますが、一般的に約束がどのように機能するかを尋ねるのではなく、具体的に知りたいです:
promise を返すものに setTimeout をラップする標準/最良の方法は何ですか?私はAngularのようなものを考えています $timeout
function 、ただしAngular specific。
まず第一に、これのためのビルトインはありません。 ES2015を強化する多くのライブラリは、ブルーバードの鞭のようなものを約束します。
他の答えは、関数の実行と遅延を抑制し、キャンセルできないタイムアウトも作成すると思います。私は単にそれを次のように書くでしょう:
function delay(ms){
var ctr, rej, p = new Promise(function (resolve, reject) {
ctr = setTimeout(resolve, ms);
rej = reject;
});
p.cancel = function(){ clearTimeout(ctr); rej(Error("Cancelled"))};
return p;
}
その後、次のことができます。
delay(1000).then(/* ... do whatever */);
または
doSomething().then(function(){ return delay(1000); }).then(doSomethingElse);
ES2015の基本機能のみが必要な場合は、次のようにさらに簡単になります。
let delay = ms => new Promise(r => setTimeout(r, ms));
setTimeout
でutil.promisify
を使用してdelay
関数を取得できます。つまり、new Promise
コンストラクターを使用する必要はありません。
実装方法は次のとおりです。
function delay(duration, func) {
var args = Array.prototype.slice.call(arguments, 2);
return new Promise(function (resolve) {
setTimeout(function () {
resolve(func.apply(null, args));
}, duration);
});
}
(ES5構文は意図的に選択されています)
しかし、すでにこれを実行している共通ライブラリ、またはそれを実行するより良い方法があるかもしれません。
clearTimeout
と同様に、約束されたタイムアウトの適切なキャンセルが必要な場合-setTimeout
から直接promiseを返すのは便利ではありません。 。特に、try...finally
ブロックで ES7 async/await を使用する場合。タイムアウト操作用に別の変数を用意することをお勧めします。このアプローチを小さな await-timeout パッケージとして実装しました。次のように機能します。
import Timeout from 'await-timeout';
async function foo() {
const timeout = new Timeout();
try {
const fetchPromise = fetch('https://example.com');
const timerPromise = timeout.set(1000).then(() => console.log('Timeout!'));
await Promise.race([fetchPromise, timerPromise]);
} finally {
timeout.clear();
}
}
この例では、フェッチが成功した場合やエラーが発生した場合にタイムアウトが確実にクリアされ、console.log('Timeout!')
は呼び出されません。