.then() 优先于 Promise 之外的代码?
Precedence of .then() over code outside a Promise?
假设我们在异步函数中有一个 Promise:
(async function() {
let x = 0;
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000)
})
.then(res => {
x = 100;
})
console.log(x);
})();
控制台输出始终是 100
,而不是 0
。我在所有主流浏览器和 Node.js 上都试过了。这正是我想要看到的,但我感觉到它周围有代码味道。我不确定这是否是将值传递给 x
的安全方法。尽管我在它之前放了很多代码,但它似乎有效。除非它是异步的(比如另一个 setTimeout()
),否则一切都很好。
有人可以确认 .then()
分支是否确实优先并在 alert(x)
行之前运行,还是只是偶然发生的?
(是的,我知道有更好的方法可以做到这一点,但这是一个简化的概念验证片段。)
这是有保证的,因为 await
会阻塞直到 promise 链完成。这是因为链接到原始承诺 return 的 .then
是一个 新的 承诺,并且 await
对其进行操作。
预期的行为是 console.log 在函数启动后约 2 秒发生 运行(当承诺被解析时),在 x 已经分配之后(作为承诺链的一部分) ).
对于“代码味道”——我认为它是 cleaner to return state from promises 并避免 side-effects。但是,鉴于范围有限和保证执行顺序..
是的,这个方法是“安全的”。您明确 await
.then() 代码块 return 的 Promise。如果您的 Promise 拒绝(例如失败的网络请求),那么您的代码将会中断,因此请确保在末尾添加一个 .catch(error)。
顺便说一句,编写这段代码的更简洁的方式是这样的:
(async function() {
let x = 0;
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000)
});
x = 100;
console.log(x);
})();
如果您不需要来自 Promise 的 return 值,此代码的行为方式与您的完全相同。
编辑:
由于 Promise 确实应该提供值,您可以将其重写为:
(async function() {
let x = 0;
const res = await new Promise((resolve, reject) => {
setTimeout(() => resolve(100), 2000)
});
x = res;
console.log(x);
})();
假设我们在异步函数中有一个 Promise:
(async function() {
let x = 0;
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000)
})
.then(res => {
x = 100;
})
console.log(x);
})();
控制台输出始终是 100
,而不是 0
。我在所有主流浏览器和 Node.js 上都试过了。这正是我想要看到的,但我感觉到它周围有代码味道。我不确定这是否是将值传递给 x
的安全方法。尽管我在它之前放了很多代码,但它似乎有效。除非它是异步的(比如另一个 setTimeout()
),否则一切都很好。
有人可以确认 .then()
分支是否确实优先并在 alert(x)
行之前运行,还是只是偶然发生的?
(是的,我知道有更好的方法可以做到这一点,但这是一个简化的概念验证片段。)
这是有保证的,因为 await
会阻塞直到 promise 链完成。这是因为链接到原始承诺 return 的 .then
是一个 新的 承诺,并且 await
对其进行操作。
预期的行为是 console.log 在函数启动后约 2 秒发生 运行(当承诺被解析时),在 x 已经分配之后(作为承诺链的一部分) ).
对于“代码味道”——我认为它是 cleaner to return state from promises 并避免 side-effects。但是,鉴于范围有限和保证执行顺序..
是的,这个方法是“安全的”。您明确 await
.then() 代码块 return 的 Promise。如果您的 Promise 拒绝(例如失败的网络请求),那么您的代码将会中断,因此请确保在末尾添加一个 .catch(error)。
顺便说一句,编写这段代码的更简洁的方式是这样的:
(async function() {
let x = 0;
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000)
});
x = 100;
console.log(x);
})();
如果您不需要来自 Promise 的 return 值,此代码的行为方式与您的完全相同。
编辑: 由于 Promise 确实应该提供值,您可以将其重写为:
(async function() {
let x = 0;
const res = await new Promise((resolve, reject) => {
setTimeout(() => resolve(100), 2000)
});
x = res;
console.log(x);
})();