gpt4 book ai didi

Javascript:在没有库的情况下按系列(或顺序)运行异步任务

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:54:11 26 4
gpt4 key购买 nike

我想在循环中运行一些异步任务,但它应该按顺序执行(一个接一个)。它应该是 vanilla JS,而不是任何库。

var doSome = function(i) {
return Promise.resolve(setTimeout(() => {
console.log('done... ' + i)
}, 1000 * (i%3)));
}

var looper = function() {
var p = Promise.resolve();

[1,2,3].forEach((n) => {
p = p.then(() => doSome(n))
})

return p;
}

looper();

当前输出:

calling for ...1
calling for ...2
calling for ...3
Promise {<resolved>: 8260}
done... 3
done... 1
done... 2

预期输出:

calling for ...1
calling for ...2
calling for ...3
Promise {<resolved>: 8260}
done... 1
done... 2
done... 3

注意:请回答,如果您尝试过并且它按预期工作

最佳答案

因此,根据您在下面的评论,我认为您自己的示例代码与您的描述不太相符。我认为您想要的示例更接近以下代码段:

var doSome = function(i) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`Completing ${i}`), 1000*(i%3))
});
}

var looper = function() {
[1,2,3].forEach((n) => {
doSome(n).then(console.log);
});
}

looper();

这里,迭代数组[1, 2, 3],并为每一个生成一个异步过程。当每个异步进程完成时,我们在它们上 .then 并在控制台记录它们的解析结果。

那么,现在的问题是如何最好地对结果进行排队?下面,我将它们存储到一个数组中,然后利用 async/await为了暂停执行结果,直到它们按顺序完成。

// This is probably what you want
var doSome = function(i) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`Completing ${i}`), 1000*(i%3))
});
}

var looper = async function() {
const nums = [1,2,3];
const promises = []
nums.forEach((n) => {
console.log(`Queueing ${n}`);
promises.push(doSome(n));
});
for (let promise of promises) {
const result = await promise;
console.log(result);
}
}

looper();

现在,我们可以消除一个循环,只在最后一个完成后执行:

// Don't use this-- it is less efficient
var doSome = function(i) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`Completing ${i}`), 1000*(i%3))
});
}

var looper = async function() {
const nums = [1,2,3];
const promises = [];
for (let n of nums) {
console.log(`Queueing ${n}`);
const result = await doSome(n);
console.log(result);
};
}

looper();

但是,正如您在日志中看到的那样,这种方法在前一个异步进程完成之前不会对下一个异步进程进行排队。这是不可取的,与您的用例不匹配。我们从这个方法之前的双循环方法中得到的是,所有异步进程都会立即执行,但随后我们对结果进行排序/排队,以便它们遵循我们预定义的顺序,而不是它们解析的顺序。

更新

关于 Promise.allasync/await 和队列的预期行为:

因此,如果您想避免使用 async/await,我认为您可以编写某种实用程序:

var doSome = function(i) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`Completing ${i}`), 1000*(i%3))
});
}

function handlePromiseQueue(queue) {
let promise = queue.shift();
promise.then((data) => {
console.log(data)
if (queue.length > 0) {
handlePromiseQueue(queue);
}
})
}

var looper = function() {
const nums = [1,2,3];
const promises = []
nums.forEach((n) => {
console.log(`Queueing ${n}`);
promises.push(doSome(n));
});
handlePromiseQueue(promises);
}

looper();

但是,让我说清楚——如果用户Bergi的断言是正确的,重要的是每个异步 promise 在它解决后立即执行,只是在它们全部之前不执行它们回来,然后这可以用 Promise.all 100% 简化:

// This is probably what you want
var doSome = function(i) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(`Completing ${i}`), 1000*(i%3))
});
}

function handlePromiseQueue(queue) {
let promise = queue.shift();
promise.then((data) => {
console.log(data)
if (queue.length > 0) {
handlePromiseQueue(queue);
}
})
}

var looper = function() {
const nums = [1,2,3];
const promises = []
nums.forEach((n) => {
console.log(`Queueing ${n}`);
promises.push(doSome(n));
});
Promise.all(promises).then(() => handlePromiseQueue(promises));
}

looper();

最后,正如 Bergi 还指出的那样,我在这里玩得很随意,没有设置任何 catch。关于这些不同的 promise ——为了简洁起见,我在示例中省略了它们,但出于您的目的,您将希望包括对错误或错误请求的正确处理。

关于Javascript:在没有库的情况下按系列(或顺序)运行异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49763148/

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