Промисы должны быть хорошо знакомы всем, подумайте всего лишь о нескольких API, но действительно ли вы понимаете промисы? В этой статье собраны десять вопросов, основанных на некоторых знаниях о Promise, и вы увидите, сколько из них вы можете ответить правильно.
Все следующие промисы относятся к экземплярам промисов, а среда — Node.js.
тема один
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
результат операции:
1
2
4
3
Объяснение: Конструктор Promise выполняется синхронно,promise.then
Функции в выполняются асинхронно.
тема вторая
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then(() => {
throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
результат операции:
promise1 Promise { <pending> }
promise2 Promise { <pending> }
(node:50928) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: error!!!
(node:50928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
promise1 Promise { 'success' }
promise2 Promise {
<rejected> Error: error!!!
at promise.then (...)
at <anonymous> }
Объяснение: Обещание имеет 3 состояния: ожидание, выполнено или отклонено. Изменение состояния может быть только ожидающим->выполненным или ожидающим->отклоненным.После изменения состояния его нельзя изменить снова. Вышеприведенный promise2 не является promise1, а возвращается новый экземпляр Promise.
тема три
const promise = new Promise((resolve, reject) => {
resolve('success1')
reject('error')
resolve('success2')
})
promise
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
результат операции:
then: success1
Объяснение: разрешить или отклонить в конструкторе допустимо только для первого выполнения, а множественные вызовы не имеют никакого эффекта, повторяя вывод кода 2: как только состояние промиса изменилось, его нельзя изменить снова.
тема четвертая
Promise.resolve(1)
.then((res) => {
console.log(res)
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res)
})
результат операции:
1
2
Объяснение: Обещания могут быть связаны. Когда дело доходит до цепочки вызовов, мы обычно думаем о передачеreturn this
Реализовано, но обещания не реализованы таким образом. обещание вызывается каждый раз.then
или.catch
вернет новое обещание, тем самым реализуя связанные вызовы.
пятая тема
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('once')
resolve('success')
}, 1000)
})
const start = Date.now()
promise.then((res) => {
console.log(res, Date.now() - start)
})
promise.then((res) => {
console.log(res, Date.now() - start)
})
результат операции:
once
success 1005
success 1007
Объяснение: Обещание.then
или.catch
Может вызываться несколько раз, но здесь конструктор Promise выполняется только один раз. Другими словами, как только внутреннее состояние обещания изменится и получит значение, каждый последующий вызов.then
или.catch
получит значение напрямую.
тема шесть
Promise.resolve()
.then(() => {
return new Error('error!!!')
})
.then((res) => {
console.log('then: ', res)
})
.catch((err) => {
console.log('catch: ', err)
})
результат операции:
then: Error: error!!!
at Promise.resolve.then (...)
at ...
объяснять:.then
или.catch
Возврат объекта ошибки не приводит к ошибке, поэтому он не будет использоваться последующими.catch
Capture, необходимо изменить на одно из следующих:
return Promise.reject(new Error('error!!!'))
throw new Error('error!!!')
Поскольку возврат любого значения, не являющегося обещанием, будет заключен в объект обещания, то естьreturn new Error('error!!!')
Эквивалентноreturn Promise.resolve(new Error('error!!!'))
.
тема семь
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(console.error)
результат операции:
TypeError: Chaining cycle detected for promise #<Promise>
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
at Function.Module.runMain (module.js:667:11)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:607:3
объяснять:.then
или.catch
Возвращаемое значение не может быть самим промисом, иначе это вызовет бесконечный цикл. Похожий на:
process.nextTick(function tick () {
console.log('tick')
process.nextTick(tick)
})
тема восьмая
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
результат операции:
1
объяснять:.then
или.catch
Ожидается, что параметр будет функцией, и если будет передана не функция, произойдет проникновение значения.
тема девять
Promise.resolve()
.then(function success (res) {
throw new Error('error')
}, function fail1 (e) {
console.error('fail1: ', e)
})
.catch(function fail2 (e) {
console.error('fail2: ', e)
})
результат операции:
fail2: Error: error
at success (...)
at ...
объяснять:.then
Может принимать два параметра: первый — это функция для обработки успеха, а второй — функция для обработки ошибок..catch
да.then
Сокращение для второго параметра, но есть предостережение по их использованию:.then
Вторая функция обработки ошибок не перехватывает ошибки, выдаваемые первой успешной функцией обработки, и последующими..catch
Может поймать предыдущие ошибки. Конечно, следующий код также работает:
Promise.resolve()
.then(function success1 (res) {
throw new Error('error')
}, function fail1 (e) {
console.error('fail1: ', e)
})
.then(function success2 (res) {
}, function fail2 (e) {
console.error('fail2: ', e)
})
тема десятая
process.nextTick(() => {
console.log('nextTick')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setImmediate(() => {
console.log('setImmediate')
})
console.log('end')
результат операции:
end
nextTick
then
setImmediate
объяснять:process.nextTick
иpromise.then
Все относятся к микрозадачам, иsetImmediate
Принадлежит макрозадаче и выполняется на этапе проверки цикла обработки событий. Микрозадача выполняется между каждым этапом цикла событий (макрозадача), а микрозадача выполняется первой в начале цикла событий.
Автором этой статьи является графитовый документnswbmwодноклассник.