Javascript 使用 setTimeout 调用的承诺链未按预期运行
Javascript Promises chain with setTimeout calls not behave as expected
我有以下代码来测试 Javascript 中的异步执行,使用承诺和超时:
'use strict'
const { promisify } = require('util')
const print = (err, contents) => {
if (err) console.error(err)
else console.log(contents)
}
const opA = (cb) => {
setTimeout(() => {
cb(null, 'A')
}, 500)
}
const opB = (cb) => {
setTimeout(() => {
cb(null, 'B')
}, 250)
}
const opC = (cb) => {
setTimeout(() => {
cb(null, 'C')
}, 125)
}
const opAProm = promisify(opA)
const opBProm = promisify(opB)
const opCProm = promisify(opC)
opAProm(print).then((res) => opBProm(print).then((res) => opCProm(print)))
我期望的结果是这样的:
A
B
C
但是它只是这样打印的:
A
我一直在寻找解决方案,我找到的最相似的解决方案是这个,尽管它并没有真正帮助我:
所以我想知道如何解决这个问题,使用 promises 或 async/await。
提前致谢!
在 promise 之后,你不应该传递一个回调 - 而是只对结果 Promise 调用 .then
。如果您从这些行中删除 print
s:
opAProm(print)
而不是直接链接 Promise,它将按需要工作。
opAProm().then((resultA) => {
print(resultA);
opBProm().then((resultB) => {
print(resultB);
opCProm()
.then((resultC) => {
print(resultC);
});
})
});
或者,更好的方法:
opAProm()
.then((resultA) => {
print(resultA);
return opBProm();
}).then((resultB) => {
print(resultB);
return opCProm();
})
.then((resultC) => {
print(resultC);
});
(或使用async
/await
)
否则,如果您这样做(就像在您的原始代码中一样)
opAProm(print)
然后 cb
被推断为传递的函数 - opA
的 cb
- 它未连接到 Promise,因此进一步的链接不起作用。使用 util 的 promisify,promise 替换的回调应该是原始函数的最后一个参数 - 如果您将 another 参数组合传递给它,它将摆脱困境。除非你改变原来的函数来接受两个参数,这真的很奇怪,但会“有效”。
const opA = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'A')
finalcb();
}, 500)
}
const opB = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'B')
finalcb();
}, 250)
}
const opC = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'C')
finalcb();
}, 125)
}
const opAProm = promisify(opA)
const opBProm = promisify(opB)
const opCProm = promisify(opC)
opAProm(print)
.then(() => {
return opBProm(print);
}).then(() => {
return opCProm(print);
});
Promisify 删除了最后一个 callback
函数。意思是,传递的 print
方法在这里 没用 。相反,您将在 then/resolve
函数中获得结果并打印。正如@CertainPerformance 提到的,您可以转换为使用 promise with then in then 或使用 async-await 来简化。
const { promisify } = require("util");
const print = (err, contents) => {
if (err) console.error(err);
else console.log(contents);
};
const opA = (cb) => {
setTimeout(() => {
cb(null, "A");
}, 500);
};
const opB = (cb) => {
setTimeout(() => {
cb(null, "B");
}, 250);
};
const opC = (cb) => {
setTimeout(() => {
cb(null, "C");
}, 125);
};
const opAProm = promisify(opA);
const opBProm = promisify(opB);
const opCProm = promisify(opC);
async function main() {
const resA = await opAProm();
console.log(resA);
const resB = await opBProm();
console.log(resB);
const resC = await opCProm();
console.log(resC);
}
main();
我有以下代码来测试 Javascript 中的异步执行,使用承诺和超时:
'use strict'
const { promisify } = require('util')
const print = (err, contents) => {
if (err) console.error(err)
else console.log(contents)
}
const opA = (cb) => {
setTimeout(() => {
cb(null, 'A')
}, 500)
}
const opB = (cb) => {
setTimeout(() => {
cb(null, 'B')
}, 250)
}
const opC = (cb) => {
setTimeout(() => {
cb(null, 'C')
}, 125)
}
const opAProm = promisify(opA)
const opBProm = promisify(opB)
const opCProm = promisify(opC)
opAProm(print).then((res) => opBProm(print).then((res) => opCProm(print)))
我期望的结果是这样的:
A
B
C
但是它只是这样打印的:
A
我一直在寻找解决方案,我找到的最相似的解决方案是这个,尽管它并没有真正帮助我:
所以我想知道如何解决这个问题,使用 promises 或 async/await。 提前致谢!
在 promise 之后,你不应该传递一个回调 - 而是只对结果 Promise 调用 .then
。如果您从这些行中删除 print
s:
opAProm(print)
而不是直接链接 Promise,它将按需要工作。
opAProm().then((resultA) => {
print(resultA);
opBProm().then((resultB) => {
print(resultB);
opCProm()
.then((resultC) => {
print(resultC);
});
})
});
或者,更好的方法:
opAProm()
.then((resultA) => {
print(resultA);
return opBProm();
}).then((resultB) => {
print(resultB);
return opCProm();
})
.then((resultC) => {
print(resultC);
});
(或使用async
/await
)
否则,如果您这样做(就像在您的原始代码中一样)
opAProm(print)
然后 cb
被推断为传递的函数 - opA
的 cb
- 它未连接到 Promise,因此进一步的链接不起作用。使用 util 的 promisify,promise 替换的回调应该是原始函数的最后一个参数 - 如果您将 another 参数组合传递给它,它将摆脱困境。除非你改变原来的函数来接受两个参数,这真的很奇怪,但会“有效”。
const opA = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'A')
finalcb();
}, 500)
}
const opB = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'B')
finalcb();
}, 250)
}
const opC = (cb, finalcb) => {
setTimeout(() => {
cb(null, 'C')
finalcb();
}, 125)
}
const opAProm = promisify(opA)
const opBProm = promisify(opB)
const opCProm = promisify(opC)
opAProm(print)
.then(() => {
return opBProm(print);
}).then(() => {
return opCProm(print);
});
Promisify 删除了最后一个 callback
函数。意思是,传递的 print
方法在这里 没用 。相反,您将在 then/resolve
函数中获得结果并打印。正如@CertainPerformance 提到的,您可以转换为使用 promise with then in then 或使用 async-await 来简化。
const { promisify } = require("util");
const print = (err, contents) => {
if (err) console.error(err);
else console.log(contents);
};
const opA = (cb) => {
setTimeout(() => {
cb(null, "A");
}, 500);
};
const opB = (cb) => {
setTimeout(() => {
cb(null, "B");
}, 250);
};
const opC = (cb) => {
setTimeout(() => {
cb(null, "C");
}, 125);
};
const opAProm = promisify(opA);
const opBProm = promisify(opB);
const opCProm = promisify(opC);
async function main() {
const resA = await opAProm();
console.log(resA);
const resB = await opBProm();
console.log(resB);
const resC = await opCProm();
console.log(resC);
}
main();