向 Promise.all 添加计时器,映射
Posted
技术标签:
【中文标题】向 Promise.all 添加计时器,映射【英文标题】:Add timer to Promise.all, map 【发布时间】:2018-06-14 02:33:03 【问题描述】:我想在下面的 get 请求之间添加一些超时。我的意思是,流程应该是这样的:timeout, https://example.com/example1, timeout, https://example.com/example2, timeout, https://example.com/example3, timeout
等等(或者没有第一次超时,无论如何)。
以下功能正常工作:
function promiseGetInformationFromMultipleUrls(parts)
return Promise.all(parts.map(part =>
return request(
'url': `https://example.com/$part`,
'json': true
).then(partData => console.log("Part data was fetched: " + part); return partData.result;)
.catch(err => console.error("Error during fetching data from part: " + part + ", error code: " + err.statusCode););
));
parts 在哪里 -> example1, example2, example3....
我正在尝试通过添加计时器来做到这一点:
const timer = ms => new Promise( res => setTimeout(res, ms));
并使用它:
function promiseGetInformationFromMultipleUrls(parts)
return Promise.all(parts.map(part =>
console.log("wait 1 seconds");
timer(1000).then(_=>console.log("done"));
return request(
'url': `https://example.com/$part`,
'json': true
).then(partData => console.log("Part data was fetched: " + part); return partData.result;)
.catch(err => console.error("Error during fetching data from part: " + part + ", error code: " + err.statusCode););
));
但这是错误的流程 -> timeout, timeout, timeout,..., get request1, get request 2, get request 3
.
【问题讨论】:
“超时”是指“延迟”吗? 确实如此。超时、延迟或休眠。 Promise.all 是错误的方法。它会立即触发所有内容。你可以使用 reduce Promise 数组或使用 await。 是的,它是一次性的。嗯,谢谢,我试试改成promise.reduce。 Resolve a chain of promises with timeouts. Promise.all的可能重复 【参考方案1】:您可以将其简化为 Promise 链:
function promiseGetInformationFromMultipleUrls(parts)
return parts.reduce((chain, part) =>
chain.then((result) =>
timer(1000).then(() =>
request(/*...*/).then(res =>
result.concat(res)
)
)
),
Promise.resolve([])
);
但是那很丑,所以你可以使用 async / await 代替:
async function promiseGetInformationFromMultipleUrls(parts)
const result = [];
for(const part of parts)
await timer(1000);
result.push(await request(/*...*/));
return result;
【讨论】:
对我来说,最好的解决方案不会改变对异步进程部件功能的承诺。我的问题的承诺只是所有脚本中的 sn-p。 在第一个提案中 -parts.reduce((chain, part) =>
零件在哪里?我想将每一行添加到 url,但没有部分。
@profiler 我不明白你。你能改写一下吗?
对不起。关于第一个解决方案 - 承诺链。没有什么“部分”,只有部分。我应该在哪里切片并在请求部分使用?
@profiler part
是您的 parts
数组的一个元素。【参考方案2】:
以下应该有效:
const Fail = function(reason)this.reason=reason;;
const isFail = x=>(x&&x.constructor)===Fail;
const timedoutPromise = time => promise =>
Promise.race([
promise,
new Promise(
(resolve,reject)=>
setTimeout(
x=>reject("timed out"),
time
)
)
]);
utls = [];//array of urls
in5Seconds = timedoutPromise(5000);
Promise.all(
urls.map(
url=>
in5Seconds(makeRequest(url))
.catch(e=>new Fail([e,url]))//failed, add Fail type object
)
)
.then(
results=>
const successes = results.filter(x=!isFail(x));
const failed = results.filter(isFail);
const timedOut = failed.filter(([e])=>e==="timed out");
)
【讨论】:
以上是关于向 Promise.all 添加计时器,映射的主要内容,如果未能解决你的问题,请参考以下文章
向 iOS 应用程序添加正在运行的计数显示计时器,例如时钟秒表?
使用 promises 索引映射 Promise.all 输出