Почему сообщение о разрешении появляется первым?
Я пытаюсь сосредоточиться на обещаниях в 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):
Как видите, все ваши 10 обещаний создаются до того, как выполнится любое из них (разрешить/отклонить).
Интересно, что в вашем коде разрешенные обещания обрабатываются первыми.
Если вы определите обработчики в двух отдельных определениях, вы получите ожидаемые результаты:
p.then((message) => {
console.log(message)
})
p.catch((message) => {
console.log(message)
})
Выход:
Ответ 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