Javascript承诺不会按预期工作
大家好,我正在努力理解javascript中承诺的概念。我已经编写了这个非常简单的程序来实现这一点。但是我得到的输出顺序并不是我期望的。我期望输出顺序是: 在func之后 外面的一切 0 0 495510 496506 497503 498501 但我得到的是相反的结果。我希望得到上面的输出,因为代码应该是非阻塞的,因为我使用的是Promise。因此程序应该继续执行。但是从实际的输出来看,我得到的结果似乎是调用func()后代码阻塞了代码。我在这里做错了什么?我应该改变什么以获得所需的输出,我在这里遗漏了什么?下面是代码,上面附有一个屏幕截图Javascript承诺不会按预期工作,javascript,typescript,promise,es6-promise,nonblocking,Javascript,Typescript,Promise,Es6 Promise,Nonblocking,大家好,我正在努力理解javascript中承诺的概念。我已经编写了这个非常简单的程序来实现这一点。但是我得到的输出顺序并不是我期望的。我期望输出顺序是: 在func之后 外面的一切 0 0 495510 496506 497503 498501 但我得到的是相反的结果。我希望得到上面的输出,因为代码应该是非阻塞的,因为我使用的是Promise。因此程序应该继续执行。但是从实际的输出来看,我得到的结果似乎是调用func()后代码阻塞了代码。我在这里做错了什么?我应该改变什么以获得所需的输出,我在
function func() {
return new Promise((resolve,reject)=>{
for(var i=0;i<1000;i++){
console.log(sum)
sum+=i;
}
if(sum>200){
resolve("Greater than ")
}
else{
reject("Error:")
}
})}
async function somefunction(){
func()
console.log("after func")
}
somefunction()
console.log("Outside everything")
函数func(){
返回新承诺((解决、拒绝)=>{
对于(变量i=0;i200){
决心(“大于”)
}
否则{
拒绝(“错误:”)
}
})}
异步函数somefunction(){
func()
console.log(“在func之后”)
}
somefunction()
console.log(“外部一切”)
异步函数和承诺在函数完成之前返回
以下是您的代码的固定版本:
function func() {
return new Promise((resolve,reject)=>{
for(var i=0;i<1000;i++){
console.log(sum)
sum+=i;
}
if(sum>200){
resolve("Greater than ")
}
else{
reject("Error:")
}
})}
async function somefunction(){
func()
console.log("after func")
}
somefunction().then(() => {
console.log("Outside everything")
})
函数func(){
返回新承诺((解决、拒绝)=>{
对于(变量i=0;i200){
决心(“大于”)
}
否则{
拒绝(“错误:”)
}
})}
异步函数somefunction(){
func()
console.log(“在func之后”)
}
somefunction()。然后(()=>{
console.log(“外部一切”)
})
这可能就是它的外观
(async () => {
// Using IIFE (immediately invoked function expression) as somefunction is async
// But this is optional
function func () {
return new Promise((resolve,reject) => {
// add sum variable
let sum = 0
for (let i = 0;i < 10;i++) { // for simplicity using 10
sum += i
console.log(sum)
}
if (sum > 5) { // for simplicity using 5
resolve('Greater than ')
} else {
reject('Error:')
}
})
}
async function somefunction () {
try {
// await func to be resolved
const result = await func() // get result from resolve call
console.log(result)
} catch (e) {
console.log(e) // get result from reject call
}
console.log('after func')
}
// wait until somefunction finishes, its necessary to void console.log('Outside everything') being called immediately
await somefunction()
console.log('Outside everything')
})()
这里需要理解的关键是,承诺始终保证在当前运行(即当前执行块)结束时得到解决,即使它们看起来是“立即”解决的。即:
Promise.resolve().then(() => console.log('a'));
console.log('b'); //"b", "a" - NOT "a", "b"
(进一步阅读:我在《承诺指南》的第三部分中详细讨论了这一概念。)
记住这一点,让我们看看发生了什么
首先调用func()
。不要被它前面的async
所迷惑;它仍然是一个同步函数调用,因此它的操作首先发生async
只是作为一个“提示”,它的主体将执行异步操作,而不是它本身是异步的
这些操作中的第一个涉及承诺,因此基于上述内容,我们知道它们将在同步console.log()之后最后解决。当这些操作被推到队列的后面时,我们转到第二个操作,即输出“after func”
这是函数的结尾,因此执行流返回到该函数的调用者范围。它发现接下来要做的事情是“在一切之外”输出
这就是执行流程的结束(“记住,当前运行”),因此承诺(数字)现在可以自由解析和输出。为什么会有async
?这并没有给脚本添加任何有用的内容。是的,这是因为如果需要的话,我会在func()语句之前使用wait。我只是在这里尝试不同的方法来更好地理解这个概念。在这个演示中,我删除了func()前面的wait。“代码应该是非阻塞的,因为我使用的是Promise”-不。当代码使用一些本机异步内容(如超时)时,它是非阻塞的,但您的代码不是。newpromise
构造函数不做任何非阻塞的东西,它提供的输出与我的案例(在屏幕截图中)完全相同。这也不是我想要的。我完全理解你做了什么,因为我习惯了用这种方式使用承诺(如你所示)。但这不是我想要的。我想在屏幕上首先或第二次打印外部的所有内容。就像非阻塞代码一样,不需要使用wait here。谢谢。我在func()中添加了console.log(),因为我试图模拟func()中的某个任务。该任务将需要一些时间。而当该任务在func()中进行时,我们的主程序将继续执行它自己的工作。这就是为什么我希望外部的所有内容都首先或第二次打印,然后从func()内部打印所有的console.log()。有办法吗?也就是说,当func()内部正在进行一些繁重的计算时,程序中的所有其他内容都会随之进行,而不是在func()完成之后。
Promise.resolve().then(() => console.log('a'));
console.log('b'); //"b", "a" - NOT "a", "b"