1. Жизненный опыт Promise
1. История обещаний
Промисы — это решение для асинхронного программирования, большее, чем наше традиционноеПерезвоните,мероприятиеЭто более разумно. Это было впервые предложено и реализовано сообществом. ES6 подумал, что это нормально, поэтому он был записан в стандарт языка, унифицирован грамматику и предоставил собственный объект Promise.
Так называемый Promise на самом деле представляет собой контейнер, в котором хранится результат события (обычно асинхронной операции), которое завершится в будущем. В синтаксисе javascript это объект, из которого можно получить информацию об асинхронных операциях. Promise предоставляет единый API, различные асинхронные операции могут обрабатываться одним и тем же методом.
2. Особенности промисов
Особенность 1: Внешний мир не влияет на состояние объекта Promise. Представляет асинхронную операцию с тремя состояниями: Pending (выполняется), Fulfilled (успешно) и Reject (сбой). Только результат асинхронной операции может определить, какое состояние находится в данный момент, и никакая другая операция не может изменить это состояние, являющееся источником Promise. «Обязательство» означает, что другие средства не могут быть изменены.
Особенность 2: как только состояние изменится, оно больше не изменится. Этот результат можно получить в любой момент. Есть только две возможности изменить состояние объекта Promise: с Pending на Fulfilled и Pending на Rejected. При возникновении этих двух ситуаций состояние будет заморожено и не изменится, но всегда будет поддерживать такой результат, который в это время станет Resolved. Даже если изменение произошло, добавление функции обратного вызова к объекту Promise немедленно даст этот результат. Это совсем другое, чем событие, все мы знаем характеристики события, если мы его пропустим, то не сможем следить за результатом.
2. Основное использование
ES6 предусматривает, что объект Promise — это функция-конструктор, которая используется для создания экземпляра Promise.
let Promise=new Promise(function(resolve,reject){
/*逻辑代码*/
if(/*异步操作成功*/){
resolve(value)
}else{
reject(error)
}
})
Конструктор Promise будет принимать два параметра: два параметра функции, resolve и reject, которые предоставляются движком javascript, и их не нужно развертывать самостоятельно.
Роль функции разрешения состоит в том, чтобы изменить статус объекта Promise с «незавершенного» на «успешный» (то есть с Pending на Resolved), а при успешном выполнении асинхронной операции результат асинхронной операции передается в в качестве параметра; Функция отклонения Функция предназначена для изменения состояния объекта Promise с «незавершенного» на «сбой» (то есть с «Ожидание» на «Отклонено»), вызова в случае сбоя асинхронной операции и передачи асинхронной ошибки.
После создания экземпляра Promise метод then можно использовать для указания функций обратного вызова для состояний Resolve и Reject соответственно.
let Promise=new Promise(function(resolve,reject){})
Promise.then(function(value){
//success
},function(error){
//failuer
})
Метод then может принимать в качестве параметров две callback-функции. Первая вызывается, когда объект Promise становится Resolved, а вторая вызывается, когда состояние объекта Promise становится Rejected.Вторая функция не является обязательной или не является Write, обе функции принимают исходящее значение объекта Promise в качестве параметра. Возьмите каштан:
function timeout(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms,'done')
})
}
timeout(100).then((value)=>{
console.log(value)
})
В приведенном выше коде метод timeout вернет экземпляр Promise. Результат произойдет через определенный период времени. По истечении указанного времени (мс) экземпляр Promise станет Resolve, что вызовет функцию обратного вызова, связанную с тогда метод. .
Promise инициализирует экземпляр и будет выполнен сразу после этого. Взгляните на следующую проверку печати:
let promise=new Promise(function(resolve,reject){
console.log("我是Promise")
resolve()
})
promise.then(function(){
comsole.log("我时候then的回调")
})
console.log('hello,promise!')
//我是Promise
//hello,promise!
//我时候then的回调
В приведенном выше коде Promise будет выполняться сразу после создания экземпляра, поэтому первым выходом является Promise, а затем функция обратного вызова, указанная методом then, будет выполняться после выполнения всех синхронных сценариев текущего сценария, поэтому в приведенном выше код, последний вывод "I then Callback".
Возьмем каштан для асинхронной загрузки изображений страниц:
function loadImageAsync(url){
retutn new Promise(function(resolve,reject){
var image=new Image();
image.onload=function(){
resolve(image)
}
image.onerror=function(){
reject(new Error('could not load image at'+url))
}
image.src=url
})
}
Каштаны, обычно используемые для предотвращения блокировки страниц асинхронной загрузки изображений, перечислены выше.Если загрузка прошла успешно, вызывается метод разрешения, в противном случае вызывается метод отклонения.
Если этого недостаточно, давайте просто реализуем текущие одностраничные популярные фреймворки Vue и React, а также используем аксиомы запроса Http и выборку для реализации процесса Ajax на основе Promise:
let getJSON=function(url){
let promise=new Promise(function(){
let client=new XMLHttpRequest()
client.open('GET',url)
client.onreadystatechange=hander
cilent.responseType='json'
client.setRequestHeader('Accept',"application/json")
client.send()
function hander(){
if(this.readystate!=4){
return
}
if(this.statues===200){
resolve(this.response)
}else{
reject(new Error(this.stautsText))
}
}
})
return promise
}
//使用
getJSON('/xxx/xx.json').then((json)=>{
console.log('contents'+json)
},(error)=>{
console.log("请求出错"+error)
})
В приведенном выше коде getJSON представляет собой инкапсуляцию объекта XMLHttpRequest на основе обещаний. Он может выдавать HTTP-запрос для данных json и возвращать объект обещания. Вы можете видеть, что функции разрешения и отклонения внутри getJSON имеют параметры, затем эти параметры будут быть переданным. Для функции обратного вызова параметр функции отклонения обычно является экземпляром объекта Error, указывающим, что возникла ошибка. В дополнение к обычному значению параметр функции разрешения также может быть другим экземпляром обещания, Например:
let pro1=new Promise(function(resolve,reject){
//....
})
let pro2=new Promise(function(resolve,reject){
//...
resolve(pro1)
})
В приведенном выше коде и pro1, и pro2 являются экземплярами promise, но метод resolve pro2 принимает pro1 в качестве параметра, то есть результат одной асинхронной операции возвращает результат другой асинхронной операции. В это время статус pro1 будет передан pro2, то есть pro1 определяет статус pro2.Если статус pro1 находится на рассмотрении, то функция обратного вызова pro2 будет ждать разрешения статуса pro1 или отклонено, то функция обратного вызова pro2 будет немедленно реализована.
3. Обещание.прототип.затем()
Экземпляр Promise имеет метод then, то есть метод then определен в объекте-прототипе Promise.prototype, и его функция заключается в добавлении функции обратного вызова к экземпляру Promise при изменении состояния. Первый параметр метода then — это функция обратного вызова состояния Resolve, а второй — функция обратного вызова состояния Rejected (необязательно).
Метод then возвращает новый экземпляр Promise, а не исходный экземпляр Promise, поэтому можно использовать цепочку, то есть другой метод then вызывается после метода then.
getJSON('xxx/xx.json').then(function(json){
return json.post
}).tnen(function(post){
})
Используя chained then, можно указать набор функций обратного вызова, которые вызываются последовательно.В это время предыдущая функция обратного вызова может возвращать асинхронную операцию, то есть экземпляр промиса, а последняя функция обратного вызова будет ожидать состояния промиса. объект для изменения перед вызовом.
4. Обещание.прототип.поймать()
Метод Promise.prototype.catch является псевдонимом .then(null, rejection), который используется для указания функции обратного вызова при возникновении ошибки.
Возьмите каштан:
getJSON('xxx/xx.json').then(function(json){
//...
}).catch(function(err){
console.log('错误'+error)
})
В приведенном выше коде, пока асинхронная операция затем выдает ошибку и статус становится отклоненным, она будет перехвачена функцией catch(), а затем указана ее функция обратного вызова для обработки ошибки. Ошибка объекта Promise имеет механизм всплытия и будет передаваться назад до тех пор, пока не будет перехвачена обработчиком catch(), что означает, что ошибка будет перехвачена следующим оператором catch.
getJSON('xxx/xx.json').then(function(json){
//...some code1
}).then(function(json){
//...some code2
}).catch(function(err){
console.log('错误'+error)
})
В приведенном выше коде всего четыре объекта Promise: сгенерировано getJSON, два затем сгенерированы два, каждый из которых сообщает об ошибке, будет пойман последним catch.В общем случае будьте осторожны, чтобы не определить функцию обратного вызова Rejected в then(). , официальная рекомендация — всегда использовать метод catch для обработки обратных вызовов исключений ошибок.
Разница между .catch() и традиционным try/catch заключается в том, что если вы не используете метод catch для указания неправильной функции обратного вызова, ошибка, выданная объектом Peomise, не будет передана внешнему коду, то есть , try/catch не ответит.
var errorNotCatch=function(){
return new Promise((resolve,reject)=>{
fs.readFile('././xxx',(err)=>{
resolve(data)
})
})
}
errorNotCatch().then(data=>{
console.log('good');
})
код выше. Попытка/поймать, которая не выдаст хороший результат, не поймает ошибку, но браузер напечатает «данные не определены»
Пятерки,
Друзья, вышеизложенное основное введение, я надеюсь лучше понять некоторые вещи, которые вы реализовали в Promise в разработке Vue и React.