用例 - 获取一堆 url 并缓存结果。快速完成的(例如 500 毫秒)会合并到此传递中,任何需要比该时间更长的时间仍然完成并保存到缓存中,因此下一轮(在我们的应用程序中大约 10 分钟后)它们会在缓存中。
我希望能够执行类似
Promise.someWithTimeout(promises, timeout)
的操作,其中结果是在超时到期之前完成的解析值数组。 (Promise.some()
真的很接近,需要计数而不是超时)
类似的东西
Promise.someWithTimeout([promises], <timeout value>)
.then((results) => {
//stuff
})
每个承诺的样子
return memcache.getAsync(keyFromUrl(url))
.then((cacheRes) => {
if(cacheRes) return cacheRes;
//not in cache go get it
return rp(url)
.then((rpRes) => {
//Save to cache but don't wait for it to complete
memcache.setAsync(keyFromUrl(url), rpRes, 86400).catch((e) => { /*error logging*/ })
return rpRes;
})
})
我们的想法是,如果 url 返回得很快,我们就使用它,如果需要更长的时间,我们就放弃但仍然缓存结果,这样下次我们就可以得到它。因此
rp()
超时会比 Promise.someWithTimeout()
超时长得多
有人写过一个库来做到这一点(我找不到),或者有更好的模式吗?我虽然考虑使用
Promise.all().timeout().finally()
并承诺将其结果存储到数组中,但感觉不对,因为我无法完全确定原因。
对于一次性编码,您可以启动两个单独的 Promise 链并使用一个标志来查看是否已经发生超时:
var timedOut = false;
// your regular code
Promise.all(...).then(function() {
// cache the result, even if it came in after the timeout
if (!timedOut) {
// if we didn't time out, then show the response
}
});
Promise.delay(1000).then(function() {
timedOut = true;
// do whatever you want to do on the timeout
});
如果您想将此功能打包到一个方法中,并且能够访问超时的事实以及即使在超时后也能访问最终结果(例如,您可以缓存它们),那么您必须解决包含不止一条信息的东西。这是一种允许访问超时和最终数据的方法,方法是使用可以包含多条信息的对象进行解析。
Promise.someWithTimeout = function(promiseArray, cnt, timeout) {
var pSome = Promise.some(promiseArray, cnt).then(function(results) {
return {status: "done", results: results};
});
var pTimer = Promise.delay(timeout).then(function() {
return {status: "timeout", promise: pSome}
});
return Promise.race([pSome, pTimer]);
}
// sample usage
Promise.someWithTimeout(arrayOfPromises, 3, 1000).then(function(result) {
if (result.status === "timeout") {
// we timed out
// the result of the data is still coming when result.promise is resolved if you still want access to it later
result.promise.then(function(results) {
// can still get access to the eventual results here
// even though there was a timeout before they arrived
}).catch(...);
} else {
// result.results is the array of results from Promise.some()
}
});