{ for await(let t of asynDataStreamOrGenerator-6ren">
gpt4 book ai didi

javascript - 如果循环未在给定时间内完成,如何打破 "for await ...of"循环?

转载 作者:行者123 更新时间:2023-12-04 16:23:11 24 4
gpt4 key购买 nike

如果异步循环没有在预期的时间段内完成,是否有打破异步循环的技术?
我有这样的代码:

(async()=>{
for await(let t of asynDataStreamOrGenerator){
//some data processing
}
//some other code I need to run based on whatever data collected by
//asyncDataStreamOrGenerators within given time period
})()
如果此循环未在某个时间跨度内完成,则跳出循环并进一步处理请求。

最佳答案

(另见 community wiki answer I posted 的另一种方法。)
在评论中你说:

I am designing a consensus algorithm, where every source needs to send the response within a given time frame. If some of such participants are dead!, I mean they do not send values, the loop will be held for ever!


这对我来说听起来像是超时。实现超时的常用方法是通过 Promise.race 带有一个围绕计时器机制的 promise ( setTimeout 或类似的)。 Promise.race观察你传递给它的 promise ,并在它们中的任何一个完成后立即完成(传递该履行或拒绝),而不管其他人后来如何解决。
为此,您需要以另一种方式循环而不是 for-await-of并直接而不是间接地使用结果对象的 promise 。假设你有一个效用函数:
const delay = (ms, value) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});
这将返回一个 promise ,它会在 X 毫秒后使用您提供的任何值(如果有)来履行。
然后:
(async () => {
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
if (result === GOT_TIMEOUT) {
// Didn't get a response in time
console.log("Timeout");
} else {
// Got a response
if (result.done) {
// Iteration complete
console.log("Iteration complete");
break;
}
// ...some data processing on `result.value`...
console.log(`Process ${result.value}`);
}
}
} finally {
try {
it.return?.(); // Close the iterator if it needs closing
} catch { }
}
})();
使用随机持续时间进行异步迭代器工作的实时示例,但在第三次迭代时强制超时:

const delay = (ms, value) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});

async function* example() {
for (let i = 1; i <= 6; ++i) {
const ms = i === 3 ? 600 : Math.floor(Math.random() * 100);
await delay(ms);
yield i;
}
}

(async () => {
const asynDataStreamOrGenerator = example();
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const start = Date.now();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
const elapsed = Date.now() - start;
if (result === GOT_TIMEOUT) {
// Didn't get a response in time
console.log(`Got timeout in ${elapsed}ms`);
} else {
// Got a response
if (result.done) {
// Iteration complete
console.log(`Got iteration complete result in ${elapsed}ms`);
break;
}
// ...some data processing on `result.value`...
console.log(`Got result ${result.value} to process in ${elapsed}ms`);
}
}
} finally {
try {
it.return?.(); // Close the iterator if it needs closing
} catch { }
}
})();
.as-console-wrapper {
max-height: 100% !important;
}

这是第一次迭代超时的示例,因为您似乎担心这种情况:

const delay = (ms, value) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});

async function* example() {
for (let i = 1; i <= 6; ++i) {
const ms = i === 1 ? 600 : Math.floor(Math.random() * 100);
await delay(ms);
yield i;
}
}

(async () => {
const asynDataStreamOrGenerator = example();
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const start = Date.now();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
const elapsed = Date.now() - start;
if (result === GOT_TIMEOUT) {
// Didn't get a response in time
console.log(`Got timeout in ${elapsed}ms`);
} else {
// Got a response
if (result.done) {
// Iteration complete
console.log(`Got iteration complete result in ${elapsed}ms`);
break;
}
// ...some data processing on `result.value`...
console.log(`Got result ${result.value} to process in ${elapsed}ms`);
}
}
} finally {
try {
it.return?.(); // Close the iterator if it needs closing
} catch { }
}
})();
.as-console-wrapper {
max-height: 100% !important;
}

如果您不希望处理阻止下一个值的收集,您不能 await您所做的处理(也许建立一个 promise 数组以完成该处理并在最后 Promise.all 它们)。
或者,如果您想退出整个操作:
(async () => {
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const results = [];
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
if (result === GOT_TIMEOUT) {
// Didn't get a response in time, bail
console.log("Timeout");
break;
}
// Got a response
if (result.done) {
// Iteration complete
console.log("Iteration complete");
break;
}
console.log(`Got ${result.value}`);
results.push(result.value);
}
} finally {
try {
it.return?.();
} catch { }
}
// ...code here to process the contents of `results`...
for (const value of results) {
console.log(`Process ${value}`);
}
})();
现场示例:

const delay = (ms, value) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});

async function* example() {
for (let i = 1; i <= 6; ++i) {
const ms = i === 3 ? 600 : Math.floor(Math.random() * 100);
await delay(ms);
yield i;
}
}

(async () => {
const asynDataStreamOrGenerator = example(); // For the example
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const results = [];
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const start = Date.now();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
const elapsed = Date.now() - start;
if (result === GOT_TIMEOUT) {
// Didn't get a response in time, bail
console.log(`Got timeout after ${elapsed}ms`);
break;
}
// Got a response
if (result.done) {
// Iteration complete
console.log(`Got iteration complete after ${elapsed}ms`);
break;
}
console.log(`Got value ${result.value} after ${elapsed}ms`);
results.push(result.value);
}
} finally {
try {
it.return?.();
} catch { }
}
// ...code here to process the contents of `results`...
for (const value of results) {
console.log(`Process ${value}`);
}
})();
.as-console-wrapper {
max-height: 100% !important;
}

再一次,它在第一次通过时超时,但不是每次通过(因为这在第一次超时时退出,我们看不到后续的):

const delay = (ms, value) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});

async function* example() {
for (let i = 1; i <= 6; ++i) {
const ms = i === 1 ? 600 : Math.floor(Math.random() * 100);
await delay(ms);
yield i;
}
}

(async () => {
const asynDataStreamOrGenerator = example(); // For the example
const TIMEOUT = 500; // Milliseconds
const GOT_TIMEOUT = {};
const results = [];
const it = asynDataStreamOrGenerator[Symbol.asyncIterator]();
try {
while (true) {
const p = it.next();
const start = Date.now();
const result = await Promise.race([p, delay(TIMEOUT, GOT_TIMEOUT)]);
const elapsed = Date.now() - start;
if (result === GOT_TIMEOUT) {
// Didn't get a response in time, bail
console.log(`Got timeout after ${elapsed}ms`);
break;
}
// Got a response
if (result.done) {
// Iteration complete
console.log(`Got iteration complete after ${elapsed}ms`);
break;
}
console.log(`Got value ${result.value} after ${elapsed}ms`);
results.push(result.value);
}
} finally {
try {
it.return?.();
} catch { }
}
// ...code here to process the contents of `results`...
for (const value of results) {
console.log(`Process ${value}`);
}
})();
.as-console-wrapper {
max-height: 100% !important;
}

或者两者的某种组合。你需要根据你真正在做什么来调整它,但这是一个似乎合理的方向。

在上述所有方面:
  • 替换 it.return?.();if (it.return) { it.return(); }如果您的环境还不支持可选链接。
  • 替换 catch { }catch (e) { }如果您的环境不支持可选 catch绑定(bind)呢。
  • 关于javascript - 如果循环未在给定时间内完成,如何打破 "for await ...of"循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69541047/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com