

Verstehen Sie Promise/Async Wait in einem Artikel und halten Sie sich mit über 70 % der Front-End-Leute in Verbindung
Heute werde ich Versprechen mit Ihnen teilen. Der Autor wird mit dem Dilemma des frühen asynchronen Codes beginnen, welche Probleme die Entstehung von Versprechen löst, die ultimative Lösung für die asynchrone Rückrufhölle und die Implementierung der Kernsyntax von Async /await ist nur eine Variante von generator+promise .
1. Das Dilemma des frühen asynchronen Codes
- Wie wir alle wissen, ist js Single-Threaded und zeitaufwändige Vorgänge werden vom Browser abgewickelt Warteschlange für die Ausführung, und der Autor hat es auch geteilt. Wenn Sie es verstehen, können Sie
promise
besser verstehen.promise
。 - 我以一个需求为切入点,我模拟网络请求(异步操作)
- 如果网络请求成功了,你告知我成功了
- 如果网络请求失败了,你告知我失败了
1.1 大聪明做法
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
。
- 首先当我执行
2.2 早期正确做法
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))
- 早期解决方案都是传入两个回调,一个失败的,一个成功的。那很多开发者会问这不是挺好的吗?挺简单的,js中函数是一等公民,可以传来传去,但是这样太灵活了,没有规范。
- 如果使用的是框架,还要阅读一下框架源码,正确失败的传实参的顺序,如果传参顺序错误这样是非常危险的。
2. Promise
-
Promise
(承诺),给予调用者一个承诺,过一会返回数据给你,就可以创建一个promise对象 - 当我们
new
一个promise
,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor) - 这个回调函数,我们需要传入两个参数回调函数,
reslove
,reject
(函数可以进行传参)- 当执行了
reslove
函数,会回调promise对象的.then函数 - 当执行了
reject
函数,会回调promise对象的.catche函数
- 当执行了
2.1 Executor立即执行
new Promise((resolve, reject) => { console.log(`executor 立即执行`) })
- 传入的
executor
是立即执行的
2.2 requestData 重构
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))
- 在函数中,new这个类的时候,传入的回调函数称之为
executor
(会被Promise类中自动执行) - 在正确的时候调用
resolve
函数,失败的时候调用reject
函数,把需要的参数传递出去。 - 异常处理
- 其中在
.then
方法中可以传入两个回调,您也可以查看Promise/A+规范- 第一个则是
fulfilled
的回调 - 第二个则是
rejected
的回调
- 第一个则是
- 其中在
- 那这样有什么好处呢? 看起来比早期处理的方案还要繁琐呢?
统一规范,可以增强阅读性和扩展性
小幅度减少回调地狱
2.3 promise的状态
- 首先先给大家举个栗子,把代码抽象为现实的栗子
- 你答应你女朋友,下周末带她去吃好吃的 (还未到下周末,此时状态为待定状态)
- 时间飞快,今天就是周末了,你和你女友一起吃了烤肉、甜点、奶茶...(已兑现状态)
- 时间飞快,今天就是周末了,正打算出门。不巧产品经理,因为线上出现的紧急问题,需要回公司解决一下,你(为了生活)只能委婉的拒绝一下女友,并且说明一下缘由(已拒绝状态)
- 使用
promise
的时候,给它一个承诺,我们可以将他划分为三个阶段- pending(待定),执行了executor,状态还在等待中,没有被兑现,也没有被拒绝
- fulfilled(已兑现),执行了
resolve
函数则代表了已兑现状态 - rejected(已拒绝),执行了
reject
Ich verwende eine Anforderung als Einstiegspunkt, ich simuliere eine Netzwerkanforderung (asynchroner Vorgang)
Wenn die Netzwerkanforderung erfolgreich ist, sagen Sie mir, dass sie erfolgreich ist - Wenn die Netzwerkanforderung fehlschlägt, sagen Sie mir, dass sie fehlgeschlagen ist
🎜1.1 Ein intelligenter Ansatz🎜
const promise = new Promise((resolve, reject) => { setTimeout(() => { reject('失败') resolve('成功') }, 3000); }) promise.then(res => console.log(res)).catch(err => console.log(err)) //失败
js
-Codes verstehen es als selbstverständlich zu betrachten, ist der Code tatsächlich nicht. Befolgen Sie die Reihenfolge, die Sie geschrieben haben. 🎜🎜Warum ist es also undefiniert
? 🎜🎜Zuallererst beginne ich mit der Ausführung der Funktion, wenn ich die Funktion requestData
ausführe. Wenn ein asynchroner Vorgang auftritt, wird die Ausführung des folgenden Codes nicht blockiert, da js ein Single-Thread-Vorgang ist, sodass der von Ihnen geschriebene return
nicht zurückgegeben wird, wenn er erfolgreich ist oder fehlschlägt. Dann gilt in dieser Funktion: Ich habe die asynchrone Operation beiseite gelegt. Es gibt keinen Rückgabewert, daher ist der Wert undefiniert
. 🎜🎜🎜🎜🎜2.2 Frühzeitiger korrekter Ansatz🎜
const promise = new Promise((resolve, reject) => { resolve({name: 'ice', age: 22}) }) promise.then(res => console.log(res)) // {name: 'ice', age: 22}
🎜2. Versprechen🎜🎜🎜🎜Versprechen
(Versprechen), geben Sie dem Anrufer ein Versprechen und geben Sie die Daten nach einer Weile an Sie zurück ein Versprechensobjekt🎜🎜Wenn wir ein Versprechen
neu
, müssen wir eine Rückruffunktion übergeben. Diese Funktion wird sofort ausgeführt und heißt (Executor)🎜🎜 Für diese Rückruffunktion , müssen wir zwei Parameter an die Rückruffunktion übergeben, reslove
, reject
(die Funktion kann Parameter übergeben)🎜🎜Wenn reslove
ausgeführt wird > Die Funktion ruft die .then-Funktion des Promise-Objekts zurück🎜🎜Wenn die Funktion reject
ausgeführt wird, wird die .catche-Funktion des Promise-Objekts zurückgerufen🎜🎜🎜🎜 🎜2.1 Executor wird sofort ausgeführt🎜
const promise = new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ice')
}, 3000);
}))
})
promise.then(res => console.log(res))
//3s后 ice
Nach dem Login kopierenNach dem Login kopieren🎜🎜Der eingehende executor
wird sofort ausgeführt🎜🎜🎜2.2 requestData Rekonstruktion🎜 h3>const promise = new Promise((resolve, reject) => {
resolve({
then(res, rej) {
res('hi ice')
}
})
})
promise.then(res => console.log(res))
// hi ice
Nach dem Login kopierenNach dem Login kopieren🎜🎜Wenn in der Funktion diese Klasse neu ist, heißt die übergebene Rückruffunktion executor
(sie wird automatisch in der Promise-Klasse ausgeführt)🎜🎜Rufen Sie auf zum richtigen Zeitpunkt Die Funktion „resolve
ruft die Funktion „reject“ auf, wenn sie fehlschlägt, und übergibt die erforderlichen Parameter. 🎜🎜Ausnahmebehandlung🎜🎜Zwei Rückrufe können in der .then
-Methode übergeben werden, Sie können auch Promise/A+ Spezifikation🎜🎜Der erste ist der Rückruf von erfüllt
🎜🎜Der zweite ist der Rückruf von abgelehnt
🎜 🎜🎜🎜🎜 🎜Was sind dann die Vorteile davon? Erscheint es umständlicher als die frühen Lösungen?🎜🎜Einheitliche Spezifikationen können die Lesbarkeit und Skalierbarkeit verbessern🎜🎜🎜🎜Die Rückrufhölle etwas reduzieren🎜🎜 🎜🎜🎜🎜2.3 Versprechensstatus🎜
🎜🎜Lassen Sie mich zunächst ein Beispiel geben und den Code in ein realistisches Beispiel abstrahieren.🎜🎜Sie versprechen Ihrer Freundin, sie mitzunehmen, um lecker zu essen Essen am nächsten Wochenende (es ist noch nicht nächstes Wochenende, der Status ist 🎜Ausstehender Status🎜)🎜🎜Die Zeit vergeht wie im Flug, heute ist das Wochenende, du und deine Freundin haben gegrillt, Desserts, Milchtee ... (🎜Cashed-Status🎜)🎜🎜 Die Zeit vergeht wie im Flug, heute ist Wochenende und ich habe vor, auszugehen. Leider muss der Produktmanager zum Unternehmen zurückkehren, um ein dringendes Problem zu lösen, das online aufgetreten ist. Sie können Ihre Freundin (um des Lebens willen) nur höflich ablehnen und den Grund erklären (🎜Abgelehnter Status🎜)🎜🎜🎜🎜Nutzung promise
, geben Sie ihm ein Versprechen, wir können es in drei Phasen unterteilen🎜🎜pending (ausstehend), der Executor wird ausgeführt, der Status wartet noch, wurde nicht eingehalten und wurde nicht abgelehnt🎜 🎜 erfüllt (erfüllt), die Ausführung der Funktion resolve
stellt den Status „erfüllt“ dar 🎜🎜abgelehnt (abgelehnt), die Ausführung der Funktion reject
stellt den Status „abgelehnt“ dar 🎜🎜 🎜🎜Zuallererst , solange sich der Status vom Status „Ausstehend“ in einen anderen Status ändert, kann der Status nicht mehr geändert werden🎜🎜🎜Denken Sie an den folgenden Code:🎜const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
resolve('成功')
}, 3000);
})
promise.then(res => console.log(res)).catch(err => console.log(err))
//失败
Nach dem Login kopierenNach dem Login kopieren
- 当我调用
reject
之后,在调用resolve
是无效的,因为状态已经发生改变,并且是不可逆的。
2.4 resolve不同值的区别
- 如果
resolve
传入一个普通的值或者对象,只能传递接受一个参数,那么这个值会作为then
回调的参数
const promise = new Promise((resolve, reject) => {
resolve({name: 'ice', age: 22})
})
promise.then(res => console.log(res))
// {name: 'ice', age: 22}
Nach dem Login kopierenNach dem Login kopieren
- 如果
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
Nach dem Login kopierenNach dem Login kopieren
- 如果
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
Nach dem Login kopierenNach dem Login kopieren
2.5 Promise的实例方法
- 实例方法,存放在
Promise.prototype
上的方法,也就是Promise的显示原型上,当我new Promise的时候,会把返回的改对象的 promise[[prototype]](隐式原型) === Promise.prototype (显示原型)
- 即new返回的对象的隐式原型指向了Promise的显示原型
2.5.1 then方法
2.5.1.1 then的参数
-
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
Nach dem Login kopieren
- 如果只捕获错误,还可以这样写
- 因为第二个参数是捕获异常的,第一个可以写个
null
或""
占位
const promise = new Promise((resolve, reject) => {
// resolve('request success')
reject('request error')
})
promise.then(null, rej => console.log(rej))
//request error
Nach dem Login kopieren
2.5.1.2 then的多次调用
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}
Nach dem Login kopierenNach dem Login kopieren
- 调用多次则会执行多次
2.5.1.3 then的返回值
-
then
方法是有返回值的,它的返回值是promise
,但是是promise
那它的状态如何决定呢?接下来让我们一探究竟。
2.5.1.3.1 返回一个普通值 状态:fulfilled
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}
Nach dem Login kopierenNach dem Login kopieren
- 返回一个普通值,则相当于主动调用
Promise.resolve
,并且把返回值作为实参传递到then
方法中。
- 如果没有返回值,则相当于返回
undefined
2.5.1.3.2 明确返回一个promise 状态:fulfilled
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 的返回值
Nach dem Login kopieren
- 主动返回一个
promise
对象,状态和你调用resolve
,还是reject
有关
2.5.1.3.3 返回一个thenable对象 状态:fulfilled
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
Nach dem Login kopieren
- 返回了一个thenable对象,其状态取决于你是调用了
resolve
,还是reject
2.5.2 catch方法
2.5.2.1 catch的多次调用
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
Nach dem Login kopieren
2.5.2.2 catch的返回值
- catch方法是有返回值的,它的返回值是promise,但是是promise那它的状态如何决定呢?接下来让我们一探究竟。
- 如果返回值明确一个promise或者thenble对象,取决于你调用了
resolve
还是reject
2.5.2.2.1 返回一个普通对象
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}
Nach dem Login kopieren
2.5.2.2.2 明确返回一个promise
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
Nach dem Login kopieren
- 此时
new Promise()
调用了reject
函数,则会被catch
捕获到
2.5.2.2.3 返回thenble对象
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
Nach dem Login kopieren
2.5.3 finally方法
- ES9(2018)新实例方法
- finally(最后),无论promise状态是fulfilled还是rejected都会执行一次
finally
方法
const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => console.log(res)).finally(() => console.log('finally execute'))
//finally execute
Nach dem Login kopieren
2.6 Promise中的类方法/静态方法
2.6.1 Promise.reslove
Promise.resolve('ice')
//等价于
new Promise((resolve, reject) => resolve('ice'))
Nach dem Login kopieren
- 有的时候,你已经预知了状态的结果为fulfilled,则可以用这种简写方式
2.6.2 Promise.reject
Promise.reject('ice error')
//等价于
new Promise((resolve, reject) => reject('ice error'))
Nach dem Login kopieren
- 有的时候,你已经预知了状态的结果为rejected,则可以用这种简写方式
2.6.3 Promise.all
const promise = new Promise((resolve, reject) => { resolve(new Promise((resolve, reject) => { setTimeout(() => { resolve('ice') }, 3000); })) }) promise.then(res => console.log(res)) //3s后 ice
const promise = new Promise((resolve, reject) => { resolve({ then(res, rej) { res('hi ice') } }) }) promise.then(res => console.log(res)) // hi ice
executor
(sie wird automatisch in der Promise-Klasse ausgeführt)🎜🎜Rufen Sie auf zum richtigen Zeitpunkt Die Funktion „resolve
ruft die Funktion „reject“ auf, wenn sie fehlschlägt, und übergibt die erforderlichen Parameter. 🎜🎜Ausnahmebehandlung🎜🎜Zwei Rückrufe können in der .then
-Methode übergeben werden, Sie können auch Promise/A+ Spezifikation🎜🎜Der erste ist der Rückruf von erfüllt
🎜🎜Der zweite ist der Rückruf von abgelehnt
🎜 🎜🎜🎜🎜 🎜Was sind dann die Vorteile davon? Erscheint es umständlicher als die frühen Lösungen?- 🎜🎜Einheitliche Spezifikationen können die Lesbarkeit und Skalierbarkeit verbessern🎜🎜🎜🎜Die Rückrufhölle etwas reduzieren🎜🎜 🎜🎜🎜
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' ]
- all方法的参数传入为一个可迭代对象,返回一个promise,只有三个都为
resolve
状态的时候才会调用.then
方法。 - 只要有一个promise的状态为rejected,则会回调
.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
- 当遇到rejectd的时候,后续的promise结果我们是获取不到,并且会把reject的实参,传递给catch的err形参中
2.6.4 Promise.allSettled
- 上面的
Promise.all
有一个缺陷,就是当遇到一个rejected的状态,那么对于后面是resolve
或者reject
的结果我们是拿不到的 - ES11 新增语法
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都有结果,无论是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) => {}) Promise.allSettled([promise1, promise2, promise3]).then(res => console.log(res)) // 什么都不打印
- 其中一个promise没有结果,则什么都结果都拿不到
2.6.5 Promise.race
- race(竞争竞赛)
- 优先获取第一个返回的结果,无论结果是fulfilled还是rejectd
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
2.6.6 Promise.any
- 与race类似,只获取第一个状态为fulfilled,如果全部为rejected则报错
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
3. Promise的回调地狱 (进阶)
- 我还是以一个需求作为切入点,把知识点嚼碎了,一点一点喂进你们嘴里。
- 当我发送网络请求的时候,需要拿到这次网络请求的数据,再发送网络请求,就这样重复三次,才能拿到我最终的结果。
3.1 卧龙解法
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
- 虽然能够实现,但是多层代码的嵌套,可读性非常差,我们把这种多层次代码嵌套称之为回调地狱
3.2 凤雏解法
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
- 利用了then链式调用这一特性,返回了一个新的promise,但是不够优雅,思考一下能不能写成同步的方式呢?
3.3 生成器+Promise解法
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
不是也产生了回调地狱吗? - 其实不用关心这个,我们可以发现它这个是有规律的,我们可以封装成一个自动化执行的函数,我们就不用关心内部是如何调用的了。
3.4 自动化执行函数封装
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
- 利用promise+生成器的方式变相实现解决回调地狱问题,其实就是
async await
的一个变种而已 - 最早为TJ实现,前端大神人物
- async await核心代码就类似这些,内部主动帮我们调用
.next
方法
3.5 最终解决回调地狱的办法
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
就可以实现异步代码同步写法了。
4. async/await 剖析
- async(异步的)
- async 用于申明一个异步函数
4.1 async内部代码同步执行
- 异步函数的内部代码执行过程和普通的函数是一致的,默认情况下也是会被同步执行
async function sayHi() { console.log('hi ice') } sayHi() //hi ice
4.2 异步函数的返回值
-
异步函数的返回值和普通返回值有所区别
- 普通函数主动返回什么就返回什么,不返回为
undefined
- 异步函数的返回值特点
- 明确有返回一个普通值,相当于
Promise.resolve
(返回值) - 返回一个thenble对象则由,then方法中的
resolve
,或者reject
有关 - 明确返回一个promise,则由这个promise决定
- 明确有返回一个普通值,相当于
- 普通函数主动返回什么就返回什么,不返回为
异步函数中可以使用
await
关键字,现在在全局也可以进行await
,但是不推荐。会阻塞主进程的代码执行
4.3 异步函数的异常处理
- 如果函数内部中途发生错误,可以通过try catch的方式捕获异常
- 如果函数内部中途发生错误,也可以通过函数的返回值.catch进行捕获
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
4.4 await 关键字
- 异步函数中可以使用
await
关键字,普通函数不行 - await特点
- 通常await关键字后面都是跟一个Promise
- 可以是普通值
- 可以是thenble
- 可以是Promise主动调用
resolve或者reject
- 这个promise状态变为fulfilled才会执行
await
后续的代码,所以await
后面的代码,相当于包括在.then
方法的回调中,如果状态变为rejected,你则需要在函数内部try catch
,或者进行链式调用进行.catch
操作
- 通常await关键字后面都是跟一个Promise
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
5. 结语
- 如果现在真的看不到未来是怎样,你就不如一直往前走,不知道什么时候天亮,去奔跑就好,跑着跑着天就亮了。
【相关推荐:javascript视频教程、编程基础视频】

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

So implementieren Sie mit WebSocket und JavaScript ein Online-Spracherkennungssystem. Einführung: Mit der kontinuierlichen Weiterentwicklung der Technologie ist die Spracherkennungstechnologie zu einem wichtigen Bestandteil des Bereichs der künstlichen Intelligenz geworden. Das auf WebSocket und JavaScript basierende Online-Spracherkennungssystem zeichnet sich durch geringe Latenz, Echtzeit und plattformübergreifende Eigenschaften aus und hat sich zu einer weit verbreiteten Lösung entwickelt. In diesem Artikel wird erläutert, wie Sie mit WebSocket und JavaScript ein Online-Spracherkennungssystem implementieren.

WebSocket und JavaScript: Schlüsseltechnologien zur Realisierung von Echtzeit-Überwachungssystemen Einführung: Mit der rasanten Entwicklung der Internet-Technologie wurden Echtzeit-Überwachungssysteme in verschiedenen Bereichen weit verbreitet eingesetzt. Eine der Schlüsseltechnologien zur Erzielung einer Echtzeitüberwachung ist die Kombination von WebSocket und JavaScript. In diesem Artikel wird die Anwendung von WebSocket und JavaScript in Echtzeitüberwachungssystemen vorgestellt, Codebeispiele gegeben und deren Implementierungsprinzipien ausführlich erläutert. 1. WebSocket-Technologie

Einführung in die Verwendung von JavaScript und WebSocket zur Implementierung eines Online-Bestellsystems in Echtzeit: Mit der Popularität des Internets und dem Fortschritt der Technologie haben immer mehr Restaurants damit begonnen, Online-Bestelldienste anzubieten. Um ein Echtzeit-Online-Bestellsystem zu implementieren, können wir JavaScript und WebSocket-Technologie verwenden. WebSocket ist ein Vollduplex-Kommunikationsprotokoll, das auf dem TCP-Protokoll basiert und eine bidirektionale Kommunikation zwischen Client und Server in Echtzeit realisieren kann. Im Echtzeit-Online-Bestellsystem, wenn der Benutzer Gerichte auswählt und eine Bestellung aufgibt

Im täglichen Leben stoßen wir oft auf Probleme zwischen Versprechen und Erfüllung. Ob in einer persönlichen Beziehung oder einer Geschäftstransaktion: Das Einhalten von Versprechen ist der Schlüssel zum Aufbau von Vertrauen. Allerdings sind die Vor- und Nachteile eines Engagements oft umstritten. In diesem Artikel werden die Vor- und Nachteile von Verpflichtungen untersucht und einige Ratschläge gegeben, wie Sie Ihr Wort halten können. Die versprochenen Vorteile liegen auf der Hand. Erstens schafft Engagement Vertrauen. Wenn jemand sein Wort hält, lässt er andere glauben, dass er eine vertrauenswürdige Person ist. Vertrauen ist die Bindung zwischen Menschen, die Menschen mehr machen kann

So implementieren Sie ein Online-Reservierungssystem mit WebSocket und JavaScript. Im heutigen digitalen Zeitalter müssen immer mehr Unternehmen und Dienste Online-Reservierungsfunktionen bereitstellen. Es ist von entscheidender Bedeutung, ein effizientes Online-Reservierungssystem in Echtzeit zu implementieren. In diesem Artikel wird erläutert, wie Sie mit WebSocket und JavaScript ein Online-Reservierungssystem implementieren, und es werden spezifische Codebeispiele bereitgestellt. 1. Was ist WebSocket? WebSocket ist eine Vollduplex-Methode für eine einzelne TCP-Verbindung.

JavaScript und WebSocket: Aufbau eines effizienten Echtzeit-Wettervorhersagesystems Einführung: Heutzutage ist die Genauigkeit von Wettervorhersagen für das tägliche Leben und die Entscheidungsfindung von großer Bedeutung. Mit der Weiterentwicklung der Technologie können wir genauere und zuverlässigere Wettervorhersagen liefern, indem wir Wetterdaten in Echtzeit erhalten. In diesem Artikel erfahren Sie, wie Sie mit JavaScript und WebSocket-Technologie ein effizientes Echtzeit-Wettervorhersagesystem aufbauen. In diesem Artikel wird der Implementierungsprozess anhand spezifischer Codebeispiele demonstriert. Wir

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

Eine detaillierte Erklärung von Promise.resolve() erfordert spezifische Codebeispiele. Promise ist ein Mechanismus in JavaScript zur Verarbeitung asynchroner Vorgänge. In der tatsächlichen Entwicklung ist es häufig erforderlich, einige asynchrone Aufgaben zu verarbeiten, die nacheinander ausgeführt werden müssen, und die Methode Promise.resolve () wird verwendet, um ein erfülltes Promise-Objekt zurückzugeben. Promise.resolve() ist eine statische Methode der Promise-Klasse, die a akzeptiert