Aujourd'hui, je vais partager les promesses avec vous.L'auteur commencera par le dilemme des premiers codes asynchrones, quels problèmes ont été résolus par l'émergence des promesses, la solution ultime à l'enfer des rappels asynchrones et implémentera la syntaxe de base de l'attente asynchrone. , async/await n'est qu'une variante de generator+promise .
promesse
. promise
。function requestData(url) { setTimeout(() => { if (url === 'iceweb.io') { return '请求成功' } return '请求失败' }, 3000) } const result = requestData('iceweb.io') console.log(result) //undefined
js
代码的执行顺序,而不是是想当然的,代码其实并不是按照你书写的顺序执行的。undefined呢
?requestData
函数,开始执行函数。遇到了异步操作不会阻塞后面代码执行的,因为js是单线程的,所以你写的return
成功或者失败并没有返回,那我这个函数中,抛开异步操作,里面并没有返回值,所以值为undefined
。function requestData(url, successCB, failureCB) { setTimeout(() => { if (url === 'iceweb.io') { successCB('我成功了,把获取到的数据传出去', [{name:'ice', age:22}]) } else { failureCB('url错误,请求失败') } }, 3000) } //3s后 回调successCB //我成功了,把获取到的数据传出去 [ { name: 'ice', age: 22 } ] requestData('iceweb.io', (res, data) => console.log(res, data), rej => console.log(rej)) //3s后回调failureCB //url错误,请求失败 requestData('icexxx.io', res => console.log(res) ,rej => console.log(rej))
Promise
(承诺),给予调用者一个承诺,过一会返回数据给你,就可以创建一个promise对象new
一个promise
,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor)reslove
,reject
(函数可以进行传参)reslove
函数,会回调promise对象的.then函数reject
函数,会回调promise对象的.catche函数new Promise((resolve, reject) => { console.log(`executor 立即执行`) })
executor
是立即执行的function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url === 'iceweb.io') { //只能传递一个参数 resolve('我成功了,把获取到的数据传出去') } else { reject('url错误,请求失败') } }, 3000) }) } //1. 请求成功 requestData('iceweb.io').then(res => { //我成功了,把获取到的数据传出去 console.log(res) }) //2. 请求失败 //2.2 第一种写法 //url错误,请求失败 requestData('iceweb.org').then(res => {},rej => console.log(rej)) //2.2 第二种写法 //url错误,请求失败 requestData('iceweb.org').catch(e => console.log(e))
executor
(会被Promise类中自动执行)resolve
函数,失败的时候调用reject
函数,把需要的参数传递出去。.then
方法中可以传入两个回调,您也可以查看Promise/A+规范fulfilled
的回调rejected
的回调统一规范,可以增强阅读性和扩展性
小幅度减少回调地狱
promise
的时候,给它一个承诺,我们可以将他划分为三个阶段resolve
函数则代表了已兑现状态reject
const promise = new Promise((resolve, reject) => { setTimeout(() => { reject('失败') resolve('成功') }, 3000); }) promise.then(res => console.log(res)).catch(err => console.log(err)) //失败🎜🎜Tout d'abord, vous devez comprendre l'ordre d'exécution du code
js
, à la place de le prendre pour acquis. Le code n'est en fait pas conforme à l'ordre que vous avez écrit. 🎜🎜Alors pourquoi est-il indéfini
? 🎜🎜Tout d'abord, lorsque j'exécute la fonction requestData
, je commence à exécuter la fonction. Lorsqu'il rencontre une opération asynchrone, cela ne bloquera pas l'exécution du code suivant, car js est monothread, donc le return
que vous écrivez ne revient pas s'il réussit ou échoue. Ensuite, dans cette fonction, J'ai mis de côté l'opération asynchrone. Il n'y a pas de valeur de retour, donc la valeur est indéfinie
. 🎜🎜🎜🎜const promise = new Promise((resolve, reject) => { resolve({name: 'ice', age: 22}) }) promise.then(res => console.log(res)) // {name: 'ice', age: 22}🎜🎜La première solution consistait à passer deux rappels, un pour l'échec et un pour le succès. Alors de nombreux développeurs se demanderont : n’est-ce pas une bonne chose ? C'est assez simple. Les fonctions en js sont des citoyens de première classe et peuvent être transmises, mais c'est trop flexible et n'a aucune spécification. 🎜🎜Si vous utilisez un framework, vous devez également lire le code source du framework pour transmettre correctement les paramètres réels dans l'ordre qui a échoué. Il est très dangereux si les paramètres sont transmis dans le mauvais ordre. 🎜🎜
Promesse
(promesse), faites une promesse à l'appelant et vous renvoyez les données après un certain temps. un objet de promesse🎜🎜Lorsque nous nouveau
une promesse
, nous devons passer une fonction de rappel. Cette fonction est exécutée immédiatement et est appelée (exécuteur)🎜🎜 Pour cette fonction de rappel. , nous devons passer deux paramètres à la fonction de rappel, reslove
, reject
(la fonction peut passer des paramètres)🎜🎜Lorsque reslove
est exécuté > Fonction, rappellera la fonction .then de l'objet promis🎜🎜Lorsque la fonction reject
est exécutée, la fonction .catche de l'objet promis sera rappelée🎜🎜🎜🎜const promise = new Promise((resolve, reject) => { resolve(new Promise((resolve, reject) => { setTimeout(() => { resolve('ice') }, 3000); })) }) promise.then(res => console.log(res)) //3s后 ice🎜🎜Le
exécuteur
entrant est exécuté immédiatement🎜🎜const promise = new Promise((resolve, reject) => { resolve({ then(res, rej) { res('hi ice') } }) }) promise.then(res => console.log(res)) // hi ice🎜🎜Dans la fonction, lors de la création de cette classe, la fonction de rappel transmise est appelée
exécuteur
(elle sera automatiquement exécutée dans la classe Promise)🎜🎜Appelez au bon moment La fonction solve
appelle la fonction reject
lorsqu'elle échoue et passe les paramètres requis. 🎜🎜Gestion des exceptions🎜🎜Deux rappels peuvent être passés dans la méthode .then
, vous pouvez également afficher Promise/A+🎜🎜Le premier est le rappel de fulfilled
🎜🎜Le second est le rappel de rejected
🎜 🎜🎜🎜🎜 🎜Alors quels en sont les avantages ? Cela semble-t-il plus lourd que les premières solutions ?promesse
, donnez-lui une promesse, on peut la diviser en trois étapes🎜🎜en attente (en attente), l'exécuteur est exécuté, le statut est toujours en attente, n'a pas été honoré, et n'a pas été rejeté🎜 🎜 Fulfilled (rempli), l'exécution de la fonction resolve
représente le statut rempli 🎜🎜rejected (rejeté), l'exécution de la fonction reject
représente le statut rejeté 🎜🎜 🎜🎜Tout d'abord , tant que le statut passe du statut en attente à un autre statut, le statut ne peut plus être modifié🎜🎜🎜Pensez au code suivant :🎜const promise = new Promise((resolve, reject) => { setTimeout(() => { reject('失败') resolve('成功') }, 3000); }) promise.then(res => console.log(res)).catch(err => console.log(err)) //失败
reject
之后,在调用resolve
是无效的,因为状态已经发生改变,并且是不可逆的。resolve
传入一个普通的值或者对象,只能传递接受一个参数,那么这个值会作为then
回调的参数const promise = new Promise((resolve, reject) => { resolve({name: 'ice', age: 22}) }) promise.then(res => console.log(res)) // {name: 'ice', age: 22}
resolve
中传入的是另外一个Promise
,那么这个新Promise
会决定原Promise
的状态const promise = new Promise((resolve, reject) => { resolve(new Promise((resolve, reject) => { setTimeout(() => { resolve('ice') }, 3000); })) }) promise.then(res => console.log(res)) //3s后 ice
resolve
中传入的是一个对象,并且这个对象有实现then
方法,那么会执行该then
方法,then
方法会传入resolve
,reject
函数。此时的promise
状态取决于你调用了resolve
,还是reject
函数。这种模式也称之为: thenable
const promise = new Promise((resolve, reject) => { resolve({ then(res, rej) { res('hi ice') } }) }) promise.then(res => console.log(res)) // hi ice
Promise.prototype
上的方法,也就是Promise的显示原型上,当我new Promise的时候,会把返回的改对象的 promise[[prototype]](隐式原型) === Promise.prototype (显示原型)then
方法可以接受参数,一个参数为成功的回调,另一个参数为失败的回调,前面重构requestData
中有演练过。const promise = new Promise((resolve, reject) => { resolve('request success') // reject('request error') }) promise.then(res => console.log(res), rej => console.log(rej)) //request success
null
或""
占位const promise = new Promise((resolve, reject) => { // resolve('request success') reject('request error') }) promise.then(null, rej => console.log(rej)) //request error
const promise = new Promise((resolve, reject) => { resolve('hi ice') }) promise.then(res => ({name:'ice', age:22})) .then(res => console.log(res)) //{name:'ice', age:22}
then
方法是有返回值的,它的返回值是promise
,但是是promise
那它的状态如何决定呢?接下来让我们一探究竟。const promise = new Promise((resolve, reject) => { resolve('hi ice') }) promise.then(res => ({name:'ice', age:22})) .then(res => console.log(res)) //{name:'ice', age:22}
Promise.resolve
,并且把返回值作为实参传递到then
方法中。undefined
const promise = new Promise((resolve, reject) => { resolve('hi ice') }) promise.then(res => { return new Promise((resolve, reject) => { resolve('then 的返回值') }) }).then(res => console.log(res)) //then 的返回值
promise
对象,状态和你调用resolve
,还是reject
有关const promise = new Promise((resolve, reject) => { resolve('hi ice') }) promise.then(res => { return { then(resolve, reject) { resolve('hi webice') } } }).then(res => console.log(res)) //hi webice
resolve
,还是reject
const promise = new Promise((resolve, reject) => { reject('ice error') }) promise.catch(err => console.log(err)) promise.catch(err => console.log(err)) promise.catch(err => console.log(err)) //ice error //ice error //ice error
resolve
还是reject
const promise = new Promise((resolve, reject) => { reject('ice error') }) promise.catch(err => ({name:'ice', age: 22})).then(res => console.log(res)) //{name:'ice', age: 22}
const promise = new Promise((resolve, reject) => { reject('ice error') }) promise.catch(err => { return new Promise((resolve, reject) => { reject('ice error promise') }) }).catch(res => console.log(res)) //ice error promise
new Promise()
调用了reject
函数,则会被catch
捕获到const promise = new Promise((resolve, reject) => { reject('ice error') }) promise.catch(err => { return { then(resolve, reject) { reject('ice error then') } } }).catch(res => console.log(res)) //ice error then
finally
方法const promise = new Promise((resolve, reject) => { resolve('hi ice') }) promise.then(res => console.log(res)).finally(() => console.log('finally execute')) //finally execute
Promise.resolve('ice') //等价于 new Promise((resolve, reject) => resolve('ice'))
Promise.reject('ice error') //等价于 new Promise((resolve, reject) => reject('ice error'))
fulfilled 状态
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi ice') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi panda') }, 2000); }) const promise3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi grizzly') }, 3000); }) Promise.all([promise1, promise2, promise3]).then(res => console.log(res)) //[ 'hi ice', 'hi panda', 'hi grizzly' ]
resolve
状态的时候才会调用.then
方法。.catch
方法rejected状态
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi ice') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi panda') }, 2000); }) const promise3 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi grizzly') }, 3000); }) Promise.all([promise1, promise2, promise3]).then(res => console.log(res)).catch(err => console.log(err)) //hi panda
Promise.all
有一个缺陷,就是当遇到一个rejected的状态,那么对于后面是resolve
或者reject
的结果我们是拿不到的Promise.allSettled
,无论状态是fulfilled/rejected都会把参数返回给我们所有promise都有结果
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi ice') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi panda') }, 2000); }) const promise3 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi grizzly') }, 3000); }) Promise.allSettled([promise1, promise2, promise3]).then(res => console.log(res)) /* [ { status: 'rejected', reason: 'hi ice' }, { status: 'fulfilled', value: 'hi panda' }, { status: 'rejected', reason: 'hi grizzly' } ] */
其中一个promise没有结果
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi ice') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi panda') }, 2000); }) const promise3 = new Promise((resolve, reject) => {}) Promise.allSettled([promise1, promise2, promise3]).then(res => console.log(res)) // 什么都不打印
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi error') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi panda') }, 2000); }) Promise.race([promise1, promise2]) .then(res => console.log(res)) .catch(e => console.log(e)) //hi error
AggregateError
const promise1 = new Promise((resolve, reject) => { setTimeout(() => { reject('hi error') }, 1000); }) const promise2 = new Promise((resolve, reject) => { setTimeout(() => { resolve('hi panda') }, 2000); }) Promise.any([promise1, promise2]) .then(res => console.log(res)) .catch(e => console.log(e)) //hi panda
function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } requestData('iceweb.io').then(res => { requestData(`iceweb.org ${res}`).then(res => { requestData(`iceweb.com ${res}`).then(res => { console.log(res) }) }) }) //iceweb.com iceweb.org iceweb.io
function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } requestData('iceweb.io').then(res => { return requestData(`iceweb.org ${res}`) }).then(res => { return requestData(`iceweb.com ${res}`) }).then(res => { console.log(res) }) //iceweb.com iceweb.org iceweb.io
function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } function* getData(url) { const res1 = yield requestData(url) const res2 = yield requestData(res1) const res3 = yield requestData(res2) console.log(res3) } const generator = getData('iceweb.io') generator.next().value.then(res1 => { generator.next(`iceweb.org ${res1}`).value.then(res2 => { generator.next(`iceweb.com ${res2}`).value.then(res3 => { generator.next(res3) }) }) }) //iceweb.com iceweb.org iceweb.io
getData
已经变为同步的形式,可以拿到我最终的结果了。那么很多同学会问,generator一直调用.next
不是也产生了回调地狱吗?function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } function* getData() { const res1 = yield requestData('iceweb.io') const res2 = yield requestData(`iceweb.org ${res1}`) const res3 = yield requestData(`iceweb.com ${res2}`) console.log(res3) } //自动化执行 async await相当于自动帮我们执行.next function asyncAutomation(genFn) { const generator = genFn() const _automation = (result) => { let nextData = generator.next(result) if(nextData.done) return nextData.value.then(res => { _automation(res) }) } _automation() } asyncAutomation(getData) //iceweb.com iceweb.org iceweb.io
async await
的一个变种而已.next
方法function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } async function getData() { const res1 = await requestData('iceweb.io') const res2 = await requestData(`iceweb.org ${res1}`) const res3 = await requestData(`iceweb.com ${res2}`) console.log(res3) } getData() //iceweb.com iceweb.org iceweb.io
getData
生成器函数函数,改为async
函数,yeild
的关键字替换为await
就可以实现异步代码同步写法了。async function sayHi() { console.log('hi ice') } sayHi() //hi ice
异步函数的返回值和普通返回值有所区别
undefined
Promise.resolve
(返回值)resolve
,或者reject
有关异步函数中可以使用await
关键字,现在在全局也可以进行await
,但是不推荐。会阻塞主进程的代码执行
async function sayHi() { console.log(res) } sayHi().catch(e => console.log(e)) //或者 async function sayHi() { try { console.log(res) }catch(e) { console.log(e) } } sayHi() //ReferenceError: res is not defined
await
关键字,普通函数不行resolve或者reject
await
后续的代码,所以await
后面的代码,相当于包括在.then
方法的回调中,如果状态变为rejected,你则需要在函数内部try catch
,或者进行链式调用进行.catch
操作function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { if (url.includes('iceweb')) { resolve(url) } else { reject('请求错误') } }, 1000); }) } async function getData() { const res = await requestData('iceweb.io') console.log(res) } getData() // iceweb.io
【相关推荐:javascript视频教程、编程基础视频】