Почему сообщение о разрешении появляется первым?

Я пытаюсь сосредоточиться на обещаниях в JavaScript. У меня была иллюзия, что, как только Обещание будет выполнено, оно никогда не сможет вернуться к отклоненному. Чтобы проверить это я написал небольшой сценарий. Я вижу, что первые сообщения, которые возвращаются, - это сообщения о разрешении "1 решите 2" и т.д. Я ожидал, что первое сообщение будет "0 отклонить 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"}

Ответы

Ответ 1

Вы можете увидеть, что происходит внутри, используя консоль инструментов разработчика вашего браузера и, возможно, установив точки останова (эти статьи могут быть полезны, если вы используете Chrome или Firefox):

enter image description here

Как видите, все ваши 10 обещаний создаются до того, как выполнится любое из них (разрешить/отклонить).

Интересно, что в вашем коде разрешенные обещания обрабатываются первыми.

Если вы определите обработчики в двух отдельных определениях, вы получите ожидаемые результаты:

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

Выход:

enter image description here

Ответ 2

Дело в том, что обещания создаются для использования в качестве асинхронных вызовов, поэтому, когда вы выполняете свой цикл и для каждой итерации вы создаете новое обещание, вы создаете новые экземпляры, и каждый из них может быть выполнен в свое время.

Но что это вообще значит? Объяснение заключается в том, что когда вы создаете 10 новых обещаний в цикле, каждое обещание будет выполнено в свое время и, вероятно, испортит ваш порядок решения обещаний.

Что вы можете сделать, чтобы решить это? Вы можете использовать команду 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() который в основном решит ваш заказ, смотрите официальные документы здесь.

Ответ 3

Поскольку JavaScript является монопоточным:

  • обещание
  • EventListener
  • SetTimeout
  • setInterval

предыдущий перечисленный метод не является частью javascript enterpreter (например, V8 Engine), он делегирует цикл обработки событий, являющийся частью браузера или nodejs. больше информации здесь

По сути, этот код делегируется 3-й стороне (узел, браузер), который сам решит, когда и в каком порядке будет выполняться этот набор микрозадач, и возвращается в основной поток.

Почему следующий код:

    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');

Ответ 4

Я нашел решение здесь: MDN обещают тогда

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). Вот почему разрешение всегда появлялось первым.

Ответ 5

Так что да, все дело в размещении в цикле событий и в том, как результаты обратных вызовов снова помещаются в стек вызовов:

пример доказать это :)

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) => {
        setTimeout( () => {
          console.log(message);
        },3000)
    }).catch((message) => {
        console.log(message)
    })
}


0 reject 1
2 reject 1
4 reject 1
6 reject 1
8 reject 1
1 resolve 2
3 resolve 2
5 resolve 2
7 resolve 2
9 resolve 2

Мне стало любопытно :( хотя и не очень в реальной жизни :)

отклонение/разрешение всегда кажется неработоспособным, если оба присутствуют...

Пример 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 {
            resolve(i + ' faked resolve ' + a)
        }       
    })

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

0 fake resolve 1
1 reject 2
2 fake resolve 1
3 reject 2
4 fake resolve 1
5 reject 2
6 fake resolve 1
7 reject 2
8 fake resolve 1
9 reject 2

пример 2/все отвергают

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

        let a = 1 + (i % 2)

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

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

0 fake reject 1
1 reject 2
2 fake reject 1
3 reject 2
4 fake reject 1
5 reject 2
6 fake reject 1
7 reject 2
8 fake reject 1
9 reject 2

пример 3/resolv - отклонить заказ

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

        let a = 1 + (i % 2)

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

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

1 resolve 2
3 resolve 2
5 resolve 2
7 resolve 2
9 resolve 2
0 reject 1
2 reject 1
4 reject 1
6 reject 1
8 reject 1

пример 4/отклонить - разрешить заказ

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

        let a = 1 + (i % 2)

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

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

1 resolve 2
3 resolve 2
5 resolve 2
7 resolve 2
9 resolve 2
0 reject 1
2 reject 1
4 reject 1
6 reject 1
8 reject 1