为什么首先出现解决消息?

时间:2019-04-17 18:39:05

标签: javascript es6-promise

我正在设法把注意力集中在JavaScript中的诺言上。我当时的幻想是,一旦解决了诺言,就再也回不去了。为了测试我写了一个小脚本。我看到返回的第一条消息是解决消息“ 1 resolve 2”等。我希望第一条消息是“ 0 reject 1”。

for (let i = 0; i < 10; i++) {
    let p = new Promise((resolve, reject) => {

        let a = 1 + (i % 2)

        if (a === 2) {
            resolve(i + ' resolve ' + a)
        } else {
            reject(i + ' reject ' + a)
        }       
    })

    p.then((message) => {
        console.log(message)
    }).catch((message) => {
        console.log(message)
    })
}

在控制台上:

[Log] 1 resolve 2
[Log] 3 resolve 2
[Log] 5 resolve 2
[Log] 7 resolve 2
[Log] 9 resolve 2
[Log] 0 reject 1
[Log] 2 reject 1
[Log] 4 reject 1
[Log] 6 reject 1
[Log] 8 reject 1
< Promise {status: "pending"}

感谢您的帮助。...

阅读后

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

我明白了这段代码。捕获被删除。

for (let i = 0; i < 10; i++) {
let p = new Promise((resolve, reject) => {

        let a = 1 + (i % 2)

    if (a === 2) {
        resolve(i + ' resolve ' + a)
    } else {
        reject(i + ' reject ' + a)
    }

})

p.then((message) => {
    console.log(message)
}, failed => {
    console.log(failed)
}) 
}

在控制台上:

[Log] 0 reject 1
[Log] 1 resolve 2
[Log] 2 reject 1
[Log] 3 resolve 2
[Log] 4 reject 1
[Log] 5 resolve 2
[Log] 6 reject 1
[Log] 7 resolve 2
[Log] 8 reject 1
[Log] 9 resolve 2
< Promise {status: "pending"}

4 个答案:

答案 0 :(得分:4)

通过使用浏览器开发工具的控制台,并可能设置断点,您可以了解幕后情况(如果您使用Chrome或{{3},则本文可能会有所帮助}):

Firefox

如您所见,您的所有10个诺言都在执行(解析/拒绝)之前创建。

有趣的是,在您的代码中,首先处理了已解决的承诺。

如果在两个单独的定义中定义处理程序,则会获得预期的结果:

p.then((message) => {
        console.log(message)
    })
p.catch((message) => {
        console.log(message)
    })

输出:

enter image description here

答案 1 :(得分:2)

重点是,Promise被用作异步调用,因此,当您执行循环并为每次迭代创建一个新的Promise时,您将创建一个新的实例,并且每个实例都可以单独执行时间。

但这甚至意味着什么?原因是,当您在一个循环中创建10个新Promises时,每个Promise都会在自己的时间内执行,并且很可能会弄乱您的Promise解决顺序。

您可以怎么解决?您可以使用await命令来等待每个诺言的解决,例如下面的代码:

for (let i = 0; i < 10; i++) {
    let p = new Promise((resolve, reject) => {

        let a = 1 + (i % 2)

        if (a === 2) {
            resolve(i + ' resolve ' + a)
        } else {
            reject(i + ' reject ' + a)
        }       
    })

    await p.then((message) => {
        console.log(message)
    }).catch((message) => {
        console.log(message)
    })
}

或者您可以尝试使用Promise.all(),这将基本上为您解决订单,请参阅官方enter image description here

答案 2 :(得分:0)

因为JavaScript是单线程:

  • 承诺
  • eventListener
  • setTimeout
  • setInterval

以前列出的方法不是javascript enterpreter(例如V8 Engine)的一部分,它委托给事件循环,后者是浏览器或nodejs的一部分。 more information here

基本上,此代码委派给第三方(节点,浏览器),由第三方决定何时{该顺序}和按哪个顺序执行此microtasks集合并返回主线程。

是为什么遵循以下代码:

    let p = new Promise((resolve, reject) => {
		    resolve('micro task thread');
    });

    p.then((message) => {
        console.log(message)
    }).catch((message) => {
        console.log(message)
    });
    console.log('main thread');

将先显示“主线程”,然后显示“微任务线程”,但是您没有明显的延迟代码。这是因为所有主线程函数调用将在对eventLoop执行任务之前执行。

在大多数情况下,事件循环将在第一次出现时执行收集。

答案 3 :(得分:0)

我确实在这里找到了解决方案: MDN promise then

for (let i = 0; i < 10; i++) {
    let p = new Promise((resolve, reject) => {
        let a = 1 + (i % 2)

        if (a === 2) {
            resolve(i + ' resolve ' + a)
        } else {
            reject(i + ' reject ' + a)
        }
    })

    p.then((message) => {
        console.log(message)
    }, failed => {
        console.log(failed)
    }) 
}

promise.catch()正在调用promise.then(未定义,onreject)。这就是为什么始终要首先解决问题的原因。