函数之间错误的 promise.all() 用法?
Wrong promise.all() usage between functions?
我制作这个虚拟代码是为了更好地理解 promise 的工作原理,模仿我必须 "promisify" 的更复杂的软件。
在附加的代码中,我希望事件按以下顺序触发和记录:
- "before" 字符串
- “...检测到”列表
- 列表"done with ..."
- "after" 字符串
但是如您所见,如果您 运行 它,"after" 字符串会在第 2 步和第 3 步之间打印。
显然,我在处理异步逻辑时一定做错了什么。
感谢您的帮助!
const obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
}
let promises = [];
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const alter_value = async(row, to_add, time) => {
await delay(time);
row.value = row.value + to_add;
console.log("done with " + row.type);
return true;
}
const two = async() => {
obj.rows.forEach(async(row) => {
switch (row.type) {
case "A":
console.log("A detected");
promises.push(alter_value(row, 1, 1000))
promises.push(alter_value(row, 2, 1800))
break;
case "B":
console.log("B detected");
promises.push(alter_value(row, 5, 1400))
break;
case "C":
console.log("C detected");
promises.push(alter_value(row, 200, 2400))
break;
}
});
return promises;
}
const one = async() => {
console.log("before");
Promise.all(two()).then(console.log("after"));
}
one();
我发现您的代码至少有两个问题,解释了您得到的结果:
- 你的
two
函数不应该是 async
。 async
函数 return 隐式 Promise
。在这里你只想 return 一个你自己已经构建的 Promise
的数组,所以你需要一个普通的函数。
.then(console.log("after"))
将立即执行 console.log
:then()
需要稍后执行的函数,因此您必须将其更改为 .then(() => console.log("after"))
.
这变成:
const obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
};
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const alter_value = async (row, to_add, time) => {
await delay(time);
row.value = row.value + to_add;
console.log("done with " + row.type);
return true;
};
const two = () => {
const promises = [];
obj.rows.forEach(async(row) => {
switch (row.type) {
case "A":
console.log("A detected");
promises.push(alter_value(row, 1, 1000));
promises.push(alter_value(row, 2, 1800));
break;
case "B":
console.log("B detected");
promises.push(alter_value(row, 5, 1400));
break;
case "C":
console.log("C detected");
promises.push(alter_value(row, 200, 2400));
break;
}
});
return promises;
};
const one = async () => {
console.log('before');
Promise.all(two()).then(() => console.log('after'));
};
one();
请注意,作为 .then()
的替代方法,您也可以在 Promise.all
上简单地使用 await
,以使您的代码更加一致:
await Promise.all(two());
console.log('after');
看起来 OP 请求同步行为。
演示大纲
函数 modVal(i, value, time)
参数派生自异步函数 syncro()
参数:const sync
一个对象数组。每个对象包含 obj.rows
的索引、该索引处的值 obj.rows[i].value
以及 modVal()
.
的 Promise 中的超时时间
参数和参数: const sync = [{r: 0, v: 1, t: 1000}, ...];
seq.r: obj.rows[
数]
seq.v: obj.rows[seq.r].value +=
数
seq.t: ...resolve(obj.rows[i].value += value),
数);
sync
数组由 for...of
循环迭代。在每次迭代中 await modVal()
被同步调用。
let obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
}
const sync = [{
r: 0,
v: 1,
t: 1000
}, {
r: 0,
v: 2,
t: 1800
}, {
r: 1,
v: 5,
t: 1400
}, {
r: 2,
v: 200,
t: 2400
}];
const syncro = async(sync) => {
const modVal = (i, value, time) => {
return new Promise(resolve => {
setTimeout(() => resolve(obj.rows[i].value += value), time);
});
}
for (let seq of sync) {
await modVal(seq.r, seq.v, seq.t);
console.log(JSON.stringify(obj.rows));
}
}
syncro(sync);
.as-console-row.as-console-row::after {
content:'';
padding:0;
margin:0;
border:0;
width:0;
}
我制作这个虚拟代码是为了更好地理解 promise 的工作原理,模仿我必须 "promisify" 的更复杂的软件。 在附加的代码中,我希望事件按以下顺序触发和记录:
- "before" 字符串
- “...检测到”列表
- 列表"done with ..."
- "after" 字符串
但是如您所见,如果您 运行 它,"after" 字符串会在第 2 步和第 3 步之间打印。 显然,我在处理异步逻辑时一定做错了什么。 感谢您的帮助!
const obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
}
let promises = [];
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const alter_value = async(row, to_add, time) => {
await delay(time);
row.value = row.value + to_add;
console.log("done with " + row.type);
return true;
}
const two = async() => {
obj.rows.forEach(async(row) => {
switch (row.type) {
case "A":
console.log("A detected");
promises.push(alter_value(row, 1, 1000))
promises.push(alter_value(row, 2, 1800))
break;
case "B":
console.log("B detected");
promises.push(alter_value(row, 5, 1400))
break;
case "C":
console.log("C detected");
promises.push(alter_value(row, 200, 2400))
break;
}
});
return promises;
}
const one = async() => {
console.log("before");
Promise.all(two()).then(console.log("after"));
}
one();
我发现您的代码至少有两个问题,解释了您得到的结果:
- 你的
two
函数不应该是async
。async
函数 return 隐式Promise
。在这里你只想 return 一个你自己已经构建的Promise
的数组,所以你需要一个普通的函数。 .then(console.log("after"))
将立即执行console.log
:then()
需要稍后执行的函数,因此您必须将其更改为.then(() => console.log("after"))
.
这变成:
const obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
};
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const alter_value = async (row, to_add, time) => {
await delay(time);
row.value = row.value + to_add;
console.log("done with " + row.type);
return true;
};
const two = () => {
const promises = [];
obj.rows.forEach(async(row) => {
switch (row.type) {
case "A":
console.log("A detected");
promises.push(alter_value(row, 1, 1000));
promises.push(alter_value(row, 2, 1800));
break;
case "B":
console.log("B detected");
promises.push(alter_value(row, 5, 1400));
break;
case "C":
console.log("C detected");
promises.push(alter_value(row, 200, 2400));
break;
}
});
return promises;
};
const one = async () => {
console.log('before');
Promise.all(two()).then(() => console.log('after'));
};
one();
请注意,作为 .then()
的替代方法,您也可以在 Promise.all
上简单地使用 await
,以使您的代码更加一致:
await Promise.all(two());
console.log('after');
看起来 OP 请求同步行为。
演示大纲
函数
modVal(i, value, time)
参数派生自异步函数syncro()
参数:const sync
一个对象数组。每个对象包含obj.rows
的索引、该索引处的值obj.rows[i].value
以及modVal()
. 的 Promise 中的超时时间
参数和参数:
const sync = [{r: 0, v: 1, t: 1000}, ...];
seq.r:obj.rows[
数]
seq.v:obj.rows[seq.r].value +=
数
seq.t:...resolve(obj.rows[i].value += value),
数);sync
数组由for...of
循环迭代。在每次迭代中await modVal()
被同步调用。
let obj = {
"rows": [{
"type": "A",
"value": 0
}, {
"type": "B",
"value": 0
}, {
"type": "C",
"value": 0
}]
}
const sync = [{
r: 0,
v: 1,
t: 1000
}, {
r: 0,
v: 2,
t: 1800
}, {
r: 1,
v: 5,
t: 1400
}, {
r: 2,
v: 200,
t: 2400
}];
const syncro = async(sync) => {
const modVal = (i, value, time) => {
return new Promise(resolve => {
setTimeout(() => resolve(obj.rows[i].value += value), time);
});
}
for (let seq of sync) {
await modVal(seq.r, seq.v, seq.t);
console.log(JSON.stringify(obj.rows));
}
}
syncro(sync);
.as-console-row.as-console-row::after {
content:'';
padding:0;
margin:0;
border:0;
width:0;
}