Обещание — это объект, представляющий возможное завершение или сбой асинхронной операции. Вот объяснение промисов на MDN. Во фронтенд-разработке промисы часто используются для решения проблем с асинхронностью и обратными вызовами, чтобы избежать ада обратных вызовов и лучше организовать код, связанный с асинхронностью. В этой статье описаны мои собственные знания и опыт работы с Promise и связанными с ним async/await.
1. Три состояния Обещания
Из буквального значения Обещаниеобещать, так как это обещание, результатом обещания будет успех и неудача. Кроме того, мы не получаем результат сразу после того, как даем обещание, и нам нужно немного времени, чтобы выполнить это обещание, прежде чем мы получим результат успеха или неудачи. Обещания на самом деле построены так же, как и обещания в нашей жизни.
На приведенном выше рисунке показана структурная схема Promise. Как и промисы в нашей жизни, промисы также имеют три состояния: одно — это состояние ожидания, когда обещание выполнено, другое — состояние «Отклонено», когда обещание не выполняется, и состояние «Выполнено», когда обещание успешно выполнено.
Далее мы даем обещание во имя любви:
let love = new Promise((resolve, reject) => {
setTimeout(() => { //开始谈恋爱,不过恋爱的结果要以后才知道
let happy = Math.random() >= 0.3 ? true : false
if ( happy ) {
resolve('marry') //恋爱成功,决定结婚
} else {
reject('break') //恋爱失败,决定分手
}
}, 500)
})
love.then(result => {
console.log(result) //处理恋爱成功的回调,result是上面resolve传过来的'marry'
}).catch(result => {
console.log(result) //处理恋爱失败的回调,result是上面reject传过来的'break'
})
Приведенный выше код является простым, но полным примером промиса.Следует отметить, что Promise будет зависать при достижении состояния успеха или отказа через состояние ожидания, то есть он не будет давать сбой после достижения успешного состояния и не будет возвращаться в успешное состояние после сбоя.
Таким образом, следующее обещание должно быть в состоянии сбоя, даже если за отклонением следует разрешение. Как говорится: если любишь, пожалуйста, люби глубоко, если бросаешь, пожалуйста, будь тщательным, не двусмысленно, вреди другим и себе. Слова Платона означают, что состояние Обещания застыло.
let love = new Promise((resolve, reject) => {
reject('break')
resolve('marry')
})
love.then(result => {
console.log(result)
}).catch(result => {
console.log(result)
})
2. Несколько способов написания then и catch of Promise
Первый и наиболее распространенный способ записи — описанный выше, с использованием then для захвата состояния разрешения и catch для захвата состояния отклонения.
love.then(result => {
console.log(result)
}).catch(result => {
console.log(result)
})
Второй, не пишет catch, записывает функцию, используемую для захвата состояния Reject, в Then, но эффект тот же, что и выше
love.then(result => {
console.log(result)
}, result => {
console.log(result)
})
Третье, отдельное письмо, также возможно
love.then(result => { //只捕捉和处理成功状态
console.log(result)
})
love.catch(result => { //只捕捉和处理失败状态
console.log(result)
})
3. Быстро создайте промис, который будет успешным или провальным.
Промис поставляется с двумя методами, мы можем использовать их для быстрого создания промиса, один из нихPromise.resolve()
, обещание, используемое для создания состояния успеха; другоеPromise.reject()
, который используется для создания промиса с неудачным состоянием.
let p1 = Promise.resolve('success')
console.log(p1) // 打出来的是 Promise {'success'}
p1.then(result => {
console.log(result) //打出来上面resolve传过来的字符串'success'
})
let p2 = Promise.reject('failed') //上面是一个成功状态Promise,这是一失败状态的Promise
p2.catch(result => {
console.log(result)
})
4. ИспользуйтеPromise.all()
для обработки класса интерфейсных сценариев
В практике front-end разработки мы иногда сталкиваемся с необходимостью отправить несколько запросов и вернуть данные в соответствии с последовательностью запросов, например, мы хотим отправить три запроса a, b и c, и данные, возвращаемые этими тремя запросами равно a1. , a2, a3, и мы хотим, чтобы a1, a2, a3 возвращались в нужном нам порядке. Затем используйтеPromise.all()
Метод прекрасно решает эту проблему.
Предположим, что используется следующий код:
//模拟异步请求的函数
let request = (name, time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
let random = Math.random()
if (random >= 0.2) {
resolve(`${name}成功了`)
} else {
reject(`${name}失败了`)
}
}, time)
})
}
//构建三个Promise实例
let a = request('小明', 1000)
let b = request('小红', 500)
let c = request('小华', 1500)
//使用Promise.all(), 注意它接收的是一个数组作为参数
Promise.all([b,a,c]).then(result => {
console.log(result)
}).catch(result => {
console.log(result)
})
Скопируйте приведенный выше код и поместите его в консоль отладки браузера и выполните его несколько раз (второе выполнение необходимо обновить). Что произойдет? Как вы могли догадаться:Если все три запроса выполнены успешно, то данные, возвращаемые этими тремя запросами, упорядочиваются в том порядке, в котором были отправлены запросы, а именно ['Успешно выполнено Сяохун', "Успешно выполнено Сяомин", "Успешно выполнено Сяохуа"] и по-прежнему возвращаются. в виде массива, а при сбое одного из запросов будет возвращен только первый неудачный результат.
Конечно, кроме этой сцены,Promise.all()
Метод можно использовать и в других местах. Например, если на странице два запроса, то страница будет отображаться только после того, как будут получены данные этих двух запросов, а перед этим будет отображаться диаграмма загрузки загрузки. использоватьPromise.all()
Эту проблему тоже можно решить очень просто.
Пять, цепной вызов Обещания
Упомянутый выше метод then продолжит возвращать объект Promise после каждого использования.
let p = Promise.resolve('success')
let response = p.then(result => {
console.log(result)
})
console.log(response) //打出来的response是一个Promise对象
Поскольку возвращенное then по-прежнему является объектом Promise, то мы можем продолжить с then, но параметр, полученный then, — это содержимое возврата в предыдущем then, а содержимым этого return могут быть обычные строки, числа и т. д. ( В конце концов, он будет инкапсулирован в промис) или это может быть объект промиса, написанный вами.
Далее мы продолжаем писать пример цепного звонка, следующего за обещанием любви выше:
let love = new Promise((resolve, reject) => {
setTimeout(() => {
let happy = Math.random() >= 0.3 ? true : false
if ( happy ) {
resolve('marry')
} else {
reject('break')
}
}, 500)
})
let haveChild = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('孩子生了!')
}, 1000)
})
love.then(result => {
console.log(result)
return haveChild // 这里返回一个Promise对象,它的resolve会被下一个then捕捉
}).then(result => {
console.log(result)
return '最后,他们白头偕老!' //这里返回的字符串会传给下一个then
}).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
Здесь следует отметить, что в вызов цепочки необходимо добавить перехват, чтобы отлавливать возможные ошибки в цепочке!
6. Цепные вызовы PROMISE можно обрабатывать в бизнес-сцене
Когда нам нужно отправить несколько запросов, а более поздний запрос всегда зависит от результата предыдущего запроса,Promise的链式操作
Вот где это пригодится.
Мы используем axios для демонстрации, сам axios использует Promise для инкапсуляции, код выглядит следующим образом:
let request = (url) => {
let result = axios.get(url) //result是Promise对象
result.then(response => {
return response
}).catch(error => {
throw new Error('出错了!')
})
}
request(url0).then(response => {
return request(response.data.link)
}).then(result => {
console.log(result)
}).catch(error => {
console.log(error)
})
Приведенный выше код просто имитирует этот процесс, и некоторые места не идеальны.
Вышеизложенное - мое понимание использования Promise. Многие места не идеальны. Если есть ошибка, пожалуйста, поправьте меня вовремя!
Это мой первый пост о Наггетс! Спасибо за просмотр!