What is the best general practice to timeout a function in promise
通过超时使函数调用
我已经看到许多资源提供了类似的示例,这些示例使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | function doWithinInterval(func, timeout) { var promiseTimeout = new Promise(function (fulfill, reject) { // Rejects as soon as the timeout kicks in setTimeout(reject, timeout); }); var promiseFunc = new Promise(function (fulfill, reject) { var result = func(); // Function that may take long to finish // Fulfills when the given function finishes fulfill(result); }); return Promise.race([promiseTimeout, promiseFunc]); } |
上面使用
听起来不错,易于使用。
但是,这是在Promise中使用超时的最佳实践吗?
当然,如果我们想使用Promises对函数调用设置超时,则可以采用上述方法。行动似乎仍然是一个很好的希望。但是,这被认为是在Promise中使用超时的一种好习惯吗?如果没有,使用它的缺点是什么?
我一直在寻找替代方法,但找不到本机的Promise方法。
相反,某些外部Promise库提供了
-
蓝鸟耗材
.timeout() -
WinJS也提供
.timeout() -
Q还附带了
.timeout() 。
但是,
这取决于您所说的超时。
如果您希望该功能停止,则不会。
如果您只想停止等待,则可以(在ES6中快速启动):
1 2 3 4 | var wait = ms => new Promise(resolve => setTimeout(resolve, ms)); var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => { throw new Error("Timeout after" + ms +" ms"); })]); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var wait = ms => new Promise(resolve => setTimeout(resolve, ms)); var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => { throw new Error("Timeout after" + ms +" ms"); })]); // Example: var log = msg => div.innerHTML +="<p>" + msg +"</p>"; var failed = e => log(e.toString() +", line" + e.lineNumber); log("Waiting 5 seconds..."); timeout(wait(5000), 2000) .then(() => log("...Done.")) .catch(failed); |
1 |
如果要取消操作(使其停止),则希望该操作附带API来取消它,并且应该使用它,因为ES6 Promise不是控制界面。
可取消承诺是ES6中一个有争议的主题,但是提到的某些库确实提供了这个概念。
原生Promise.race方法在实际承诺完成后不会清除超时承诺的计时器,因此该过程将等待,直到超时承诺也完成。这意味着如果将超时设置为1h并且我们的承诺在1分钟后完成,则该过程将等待59分钟后退出。
改为使用此方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | export function race({promise, timeout, error}) { let timer = null; return Promise.race([ new Promise((resolve, reject) => { timer = setTimeout(reject, timeout, error); return timer; }), promise.then((value) => { clearTimeout(timer); return value; }) ]); } |