javascript 中异步函数的不明确行为
Ambiguous behaviour of async function in javascript
第一版代码:
console.log("before function")
function changecolor(color) {
return new Promise((reslove, request) => {
setTimeout(() => {
document.body.style.backgroundColor = color
reslove("success")
}, 2000)
})
}
changecolor("red")
.then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("green")
}).then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("orange")
}).then(e => {
console.log("changed successfully")
console.log(e)
}).catch(e => {
console.log("unsuccessful")
console.log(e)
})
console.log("last line")
第一个版本输出:
before function
last line
changed successfully
success
changed successfully
success
changed successfully
success
第二版代码:
console.log("before function")
async function changecolor(color) {
console.log("inside function")
setTimeout(() => {
document.body.style.backgroundColor = color
console.log(`color is ${color}`)
}, 2000)
console.log("function end")
return "success"
}
changecolor("red")
.then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("green")
}).then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("orange")
}).then(e => {
console.log("changed successfully")
console.log(e)
}).catch(e => {
console.log("unsuccessful")
console.log(e)
})
console.log("last line")
第二个版本输出:
before function
inside function
function end
last line
changed successfully
success
inside function
function end
changed successfully
success
inside function
function end
changed successfully
success
color is red
color is green
color is orange
我的问题: 当我 运行 第一个版本的代码然后我的 html 页面的颜色在 2 秒后变成不同的背景颜色但是在第二个版本的代码中,它会在 2 秒后同时变为所有背景颜色
我知道javascript是单线程的,当我们遇到setTimeOut()函数时它会执行代码的其他部分
即使它们两个中的代码相同,一个使用纯 promise,另一个使用 async 关键字,但即使我在第二版代码中的 setTimeOut() 函数之前使用 await 关键字,它们的输出也不同
我是 javascript 的新手,谁能帮帮我
async
函数的存在是为了简化使用 promise 的工作,但它们不会自动等待任何事情。如果您 await
一个承诺,那么该功能将暂停,等待该承诺解决,然后恢复。如果你从来没有 await
一个承诺,那么你的 async
函数将 运行 一直到完成,此时它 returns。 return 值是一个承诺,但由于您没有等待任何事情,该承诺会立即解决。
换句话说,解决方案 #2 不等待任何事情。它立即调用 changeColor,设置超时,然后它立即 1 进入 .then
再次调用 changeColor。你最终在开始时设置了一堆超时,然后 2 秒后它们都关闭了。
如果您想将 setTimeout 用作承诺,则需要将其包装在承诺中,就像您在第一个示例中所做的那样。
1) 这是作为一个微任务发生的,所以不是很同步
第一版代码:
console.log("before function")
function changecolor(color) {
return new Promise((reslove, request) => {
setTimeout(() => {
document.body.style.backgroundColor = color
reslove("success")
}, 2000)
})
}
changecolor("red")
.then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("green")
}).then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("orange")
}).then(e => {
console.log("changed successfully")
console.log(e)
}).catch(e => {
console.log("unsuccessful")
console.log(e)
})
console.log("last line")
第一个版本输出:
before function
last line
changed successfully
success
changed successfully
success
changed successfully
success
第二版代码:
console.log("before function")
async function changecolor(color) {
console.log("inside function")
setTimeout(() => {
document.body.style.backgroundColor = color
console.log(`color is ${color}`)
}, 2000)
console.log("function end")
return "success"
}
changecolor("red")
.then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("green")
}).then(e => {
console.log("changed successfully")
console.log(e)
return changecolor("orange")
}).then(e => {
console.log("changed successfully")
console.log(e)
}).catch(e => {
console.log("unsuccessful")
console.log(e)
})
console.log("last line")
第二个版本输出:
before function
inside function
function end
last line
changed successfully
success
inside function
function end
changed successfully
success
inside function
function end
changed successfully
success
color is red
color is green
color is orange
我的问题: 当我 运行 第一个版本的代码然后我的 html 页面的颜色在 2 秒后变成不同的背景颜色但是在第二个版本的代码中,它会在 2 秒后同时变为所有背景颜色
我知道javascript是单线程的,当我们遇到setTimeOut()函数时它会执行代码的其他部分
即使它们两个中的代码相同,一个使用纯 promise,另一个使用 async 关键字,但即使我在第二版代码中的 setTimeOut() 函数之前使用 await 关键字,它们的输出也不同
我是 javascript 的新手,谁能帮帮我
async
函数的存在是为了简化使用 promise 的工作,但它们不会自动等待任何事情。如果您 await
一个承诺,那么该功能将暂停,等待该承诺解决,然后恢复。如果你从来没有 await
一个承诺,那么你的 async
函数将 运行 一直到完成,此时它 returns。 return 值是一个承诺,但由于您没有等待任何事情,该承诺会立即解决。
换句话说,解决方案 #2 不等待任何事情。它立即调用 changeColor,设置超时,然后它立即 1 进入 .then
再次调用 changeColor。你最终在开始时设置了一堆超时,然后 2 秒后它们都关闭了。
如果您想将 setTimeout 用作承诺,则需要将其包装在承诺中,就像您在第一个示例中所做的那样。
1) 这是作为一个微任务发生的,所以不是很同步