//之前的異步程序定時(shí)器要后執(zhí)行养葵,先執(zhí)行同步程序
function aa() {
setTimeout(() => {
console.log('這里是定時(shí)器內(nèi)部111'); //異步程序定時(shí)器要后執(zhí)行例衍,先執(zhí)行同步程序
},0)
}
aa()
console.log("這里是同步222");
//aa()放入主程序,發(fā)現(xiàn)里面是異步程序唾那,放入異步API中恨诱,0秒結(jié)束,又加入到任務(wù)隊(duì)列抑片。執(zhí)行后面的同步語(yǔ)句,所有同步語(yǔ)句執(zhí)行完杨赤,將任務(wù)隊(duì)列里的任務(wù)加入執(zhí)行棧
//想個(gè)辦法異步程序定時(shí)器先執(zhí)行敞斋,后執(zhí)行同步程序
function aa(callback) { //第二步 callback回調(diào)函數(shù)接收,回頭有空再調(diào)用的函數(shù)
setTimeout(() => {
console.log('這里是定時(shí)器內(nèi)部111');
callback()// 第三步:等定時(shí)器執(zhí)行完了執(zhí)行callback
},0)
}
aa(function(){//第一步望拖,這里傳個(gè)函數(shù),將之前同步語(yǔ)句放進(jìn)去
console.log("這里是同步222");
})
//回調(diào)函數(shù)就是把函數(shù)作為實(shí)參傳遞給另外一個(gè)函數(shù)挫鸽,實(shí)參函數(shù)在在異步程序里執(zhí)行说敏,當(dāng)異步程序處理完了以后,再來(lái)執(zhí)行!
沒(méi)有使用后臺(tái)數(shù)據(jù)的情況
function aa() {
let num = 0;
setTimeout(()=>{
num = 50 //假設(shè)3秒后后臺(tái)返回值丢郊,把num變成了50
}, 3000)
console.log(num); //打印這一刻后臺(tái)還沒(méi)有把數(shù)據(jù)傳輸過(guò)來(lái)
}
aa()
通過(guò)回調(diào)函數(shù)使用后臺(tái)的數(shù)據(jù)的情況
function aa() {
let num = 0;
setTimeout((cb) => { // 通過(guò)回調(diào)函數(shù)使用后臺(tái)的數(shù)據(jù)
num = 50
cb(num)
}, 3000, function () {
console.log(num);
})
}
aa()
// 回調(diào)函數(shù)很容易發(fā)生回調(diào)地獄(回調(diào)處理異步會(huì)存在很多問(wèn)題)
// 實(shí)際中獲取數(shù)據(jù)不一定使用盔沫,只是驗(yàn)證權(quán)限,是一個(gè)注冊(cè)用戶等
function aa() {
let num = 0;
setTimeout(() => {
num = 'token' // 第一次先驗(yàn)證注冊(cè)用戶權(quán)限token
setTimeout(() => {
num = 60;
// setTimeout(()=>{},num)//第三次帶著參數(shù)60再發(fā)送請(qǐng)求枫匾,這就是回調(diào)地獄
}, 2000, num) //第二次拿權(quán)限token請(qǐng)求數(shù)據(jù)時(shí)架诞,要將token帶過(guò)去
}, 3000)
}
aa()
回調(diào)處理異步會(huì)存在很多問(wèn)題,es6推出了Promise
1. Promise 承諾,許諾
1.1. 概念
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件更合理和更強(qiáng)大干茉。
所以Promise谴忧,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果角虫。
1.2. 特點(diǎn)
- promise對(duì)象的狀態(tài)不受外界影響沾谓。
- 一旦狀態(tài)改變,就不會(huì)再變戳鹅,任何時(shí)候都可以得到這個(gè)結(jié)果均驶。
1.3. 狀態(tài)
Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):
- pending(進(jìn)行中)枫虏、 此時(shí)操作尚未完成
- fulfilled(resolve)(已成功) 異步操作成功
- rejected(reject)(已失敻狙ā)。 異步操作失敗
只有異步操作的結(jié)果隶债,可以決定當(dāng)前是哪一種狀態(tài)腾它,任何其他操作都無(wú)法改變這個(gè)狀態(tài)。
1.4.缺點(diǎn)
- 無(wú)法取消Promise死讹,一旦新建它就會(huì)立即執(zhí)行携狭,無(wú)法中途取消。
- 如果不設(shè)置回調(diào)函數(shù)回俐,Promise內(nèi)部拋出的錯(cuò)誤逛腿,不會(huì)反應(yīng)到外部稀并。
- 當(dāng)處于pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)单默。
1.5.用法
1.5.1 Promise基本語(yǔ)法
let promise = new Promise(function(resolve,reject){
// resolve 成功后調(diào)用
// reject 失敗后調(diào)用
})
promise.then(res => {
},err => {
})
//Promise基本操作
let promise= new Promise(function(resolve,reject){//Promise這個(gè)容器要有函數(shù)作為參數(shù)碘举,否則報(bào)錯(cuò)。函數(shù)里有兩個(gè)形參resolve(成功調(diào)用),reject(失敗調(diào)用)
// console.log(arguments); //實(shí)參列表里有兩個(gè)函數(shù)
});
console.log(promise); //有了回調(diào)函數(shù)搁廓,返回promise是個(gè)對(duì)象引颈。狀態(tài)是pending
//[[PromiseState]]: "pending" 狀態(tài)等待 不能操作
//[[PromiseResult]]: undefined 結(jié)果 不能操作
//同步語(yǔ)句的Promise
let num =0;
let promise= new Promise(function(resolve,reject){
if(num==10){
resolve(50) //成功時(shí)調(diào)用的函數(shù) 控制臺(tái):Promise {<fulfilled>: 50}。50是傳的參數(shù)
}else{
reject('承諾失敗') //失敗時(shí)調(diào)用的函數(shù) promise處理同步程序 ,控制臺(tái)會(huì)有紅色報(bào)錯(cuò)信息
}
});
console.log(promise);
// 異步語(yǔ)句的promise始終保持著同步打印的結(jié)果境蜕,沒(méi)有實(shí)時(shí)更新?tīng)顟B(tài)
let num = 10;
let promise = new Promise(function (resolve, reject) {
setTimeout(() => {
if (num == 10) {
resolve(50)
} else {
reject('承諾失敗')
}
},3000)
});
console.log(promise); //這是同步打印蝙场,三秒以后狀態(tài)已經(jīng)改變了,一直沒(méi)有通知粱年,沒(méi)有拿到改變后的狀態(tài)售滤,始終是等待期
// promise最基本的用法,內(nèi)化報(bào)錯(cuò)信息
// promise原型上then方法解決實(shí)時(shí)更新?tīng)顟B(tài)問(wèn)題台诗,內(nèi)化報(bào)錯(cuò)信息,不推送到控制臺(tái)
let num = 0;
let promise = new Promise(function (resolve, reject) {
setTimeout(() => {
if (num == 10) {
resolve(50)
} else {
reject('承諾失敗')
}
}, 3000)
});
console.log(promise);
promise.then(function (val) { //這個(gè)函數(shù)相當(dāng)于實(shí)參完箩,傳給Promise這個(gè)函數(shù)
console.log('承諾成功后調(diào)用的函數(shù)' + val);
}, function (err) { //這個(gè)函數(shù)相當(dāng)于實(shí)參,傳給Promise這個(gè)函數(shù)
console.log('承諾失敗調(diào)用的函數(shù)' + err);
})
//沒(méi)有顯示調(diào)用then方法時(shí)拉队,有報(bào)錯(cuò)信息后拋到控制臺(tái)紅色顯示弊知。調(diào)用then方法后就可以內(nèi)化掉報(bào)錯(cuò)信息,不會(huì)因此終止程序
ajax發(fā)送請(qǐng)求
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
// console.log(window.$);//一個(gè)函數(shù)粱快,jquery選擇器秩彤,有了外部鏈入的script腳本,$才管用
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts', //服務(wù)器路徑
type: 'GET',//請(qǐng)求方式事哭,默認(rèn)get
success: function (data) { //請(qǐng)求后臺(tái)成功呐舔,后臺(tái)會(huì)將數(shù)據(jù)傳給成功函數(shù)
console.log(data);
},
error: function (err) { //請(qǐng)求后臺(tái)失敗
console.log(err);
}
})
</script>
//ajax請(qǐng)求的回調(diào)地獄(一層套一層)
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success: function (data) {
console.log(data);
//第一次請(qǐng)求數(shù)據(jù)成功,發(fā)送第二次數(shù)據(jù)
let { id = 0 } = data || {}// 解構(gòu)id id 默認(rèn)值
$.ajax({
url: `https://jsonplaceholder.typicode.com/posts/${id + 2}`, //注意``
type: 'GET',
success: function (data) {
console.log(data);
//第二次請(qǐng)求數(shù)據(jù)成功慷蠕,發(fā)送第三次數(shù)據(jù)
let { id = 0 } = data || {}
$.ajax({
url: `https://jsonplaceholder.typicode.com/posts/${id + 2}`, //注意``
type: 'GET',
success: function (data) {
console.log(data);
//第三次次請(qǐng)求
let { id = 0 } = data || {}
$.ajax({
url: `https://jsonplaceholder.typicode.com/posts/${id + 2}`, //注意``
type: 'GET',
success: function (data) {
console.log(data);
//第三次請(qǐng)求
},
error: function (err) {
console.log(err);
}
})
},
error: function (err) {
console.log(err);
}
})
},
error: function (err) {
console.log(err);
}
})
},
error: function (err) {
console.log(err);
}
})
</script>
當(dāng)然珊拼,可以使用callback,但是callback使用起來(lái)是一件很讓人絕望的事情流炕。
這時(shí):Promise這個(gè)為異步編程而生的對(duì)象站了出來(lái)....
<!-- 使用Promise處理后臺(tái)異步請(qǐng)求 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
let promise = new Promise((resolve, reject) => {
$.ajax({ //發(fā)送ajax請(qǐng)求
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success: function (data) { //成功了執(zhí)行 resolve(data)澎现,相當(dāng)于執(zhí)行then方法的第一個(gè)參數(shù)
resolve(data)
},
error: function (err) {
reject(err);
}
})
})
//Promise通過(guò)then方法來(lái)處理
promise.then((data) => { // 不需要使用this,arguments所以使用箭頭函數(shù)
console.log(data); //數(shù)據(jù)執(zhí)行
}, (err) => {
console.log(err);
})
</script>
<!-- 使用Promise處理后臺(tái)異步請(qǐng)求 每辟。以上代碼的優(yōu)化-->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
let promise = new Promise((resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success:resolve, //代碼優(yōu)化
error:reject //代碼優(yōu)化
})
})
promise.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
</script>
1.5.2 then方法
ps: 如果一個(gè)對(duì)象實(shí)現(xiàn)了then方法, 這個(gè)對(duì)象就被稱之為thenable 對(duì)象, 所有的promise對(duì)象都是thenable對(duì)象(都可以調(diào)用then方法), 但是并非所有的thenable對(duì)象都是promise
promise的then返回值還是一個(gè)promise對(duì)象,多以可以連點(diǎn)使用
// 調(diào)用then方法也會(huì)返回一個(gè)新的promise剑辫,并且是成功狀態(tài),值為return的值
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
let promise = new Promise((resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success:resolve,
error:reject
})
})
let pro_then = promise.then((data) => { //調(diào)用then方法也會(huì)返回一個(gè)新的promise渠欺,并且是成功狀態(tài)妹蔽,值為return的值
console.log(data);
return new Promise((resolve,reject)=>resolve(59))
// return 50;
}, (err) => {
console.log(err);
})
console.log(pro_then);
</script>
Promise實(shí)例生成以后,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)。
也就是說(shuō)胳岂,狀態(tài)由實(shí)例化時(shí)的參數(shù)(函數(shù))執(zhí)行來(lái)決定的编整,根據(jù)不同的狀態(tài),看看需要走then的第一個(gè)參數(shù)還是第二個(gè)乳丰。
resolve()和reject()的參數(shù)會(huì)傳遞到對(duì)應(yīng)的回調(diào)函數(shù)的data或err
then返回的是一個(gè)新的Promise實(shí)例掌测,也就是說(shuō)可以繼續(xù)then
<!-- Promise的then方法可以無(wú)限調(diào)用下去,可以解決回調(diào)地獄的問(wèn)題 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
let promise = new Promise((resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success: resolve,
error: reject
})
})
let pro_then = promise.then((data) => { //調(diào)用then方法也會(huì)返回一個(gè)新的promise产园,等待的promise并且是成功狀態(tài)汞斧,值為return的值
console.log(data);
// return new Promise((resolve,reject)=>resolve(undefined))//不寫return默認(rèn)返回undefined,且是成功的
return 50;
}, (err) => {
console.log(err);
return new Promise((resolve, reject) => { reject(10) }) //失敗調(diào)用
//控制臺(tái)中這樣寫的let proerr =new Promise((resolve,reject) => {reject(10)}) 什燕,返回undefined
})
console.log(pro_then);
let proerr = new Promise((resolve, reject) => { reject(10) }) //執(zhí)行的失敗的函數(shù)
pro2_then = proerr.then(() => { }, (err) => { console.log(err); return 50 }) //第一次執(zhí)行失敗函數(shù)后粘勒,第二次又調(diào)用then方法
console.log(pro2_then); //不管上一次執(zhí)行的第一個(gè)成功函數(shù)還是第二個(gè)失敗的函數(shù),它的返回值都會(huì)自動(dòng)包裝成成功狀態(tài)
// then方法可以無(wú)限調(diào)用下去屎即,可以解決回調(diào)地獄的問(wèn)題
</script>
//通過(guò)promise 可以將ajax請(qǐng)求的回調(diào)地獄拉平庙睡。注意這個(gè)拉平只是代碼組織的拉平,原理還是一樣的
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
let promise = new Promise((resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success: resolve,
error: reject
})
})
promise.then((data) => {
console.log(data);
let { id } = data //取到所需要的id
return new Promise((resolve, reject) => { //顯示的返回一個(gè)promise
$.ajax({ //發(fā)送第二次請(qǐng)求
url: `https://jsonplaceholder.typicode.com/posts/${id + 2}`,
type: 'GET',
success: resolve,
error: reject
})
})
}, (err) => {
console.log(err);
return new Promise((resolve, reject) => { reject(10) })
})
.then((data) => { //第二次連續(xù)調(diào)用then方法
console.log(data);
let { id } = data //取到所需要的id
return new Promise((resolve, reject) => {
$.ajax({
url: `https://jsonplaceholder.typicode.com/posts/${id + 2}`,
type: 'GET',
success: resolve,
error: reject
})
})
}, (err) => {
console.log(err);
return new Promise((resolve, reject) => { reject(10) })
})
.then((data) => {
console.log(data);
})
1.6. catch()
promise.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
可以如上使用,then方法里的參數(shù)為成功后執(zhí)行,catch方法里的參數(shù)為失敗后執(zhí)行
.catch方法是.then(null, rejection)的別名剑勾,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)埃撵。
promise身上有一個(gè)catch來(lái)捕獲錯(cuò)誤
promise.catch(err => {
console.log(err);
})
// 其實(shí)就是then方法里的第二個(gè)參數(shù)
// 將then中的第二個(gè)函數(shù)移動(dòng)到了catch里
let promise = new Promise((resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts/1/',
type: 'GET',
success: resolve,
error: reject
})
})
promise.then((data) => {
console.log(data);
})
.catch((err) => { // 將then中的第二個(gè)函數(shù)移動(dòng)到了catch里
console.log(err);
return new Promise((resolve, reject) => { reject(10) })
})
//then里有兩個(gè)函數(shù)赵颅,一個(gè)成功調(diào)用的虽另,一個(gè)失敗調(diào)用的。es6可以將失敗回調(diào)函數(shù)放到catch里
1.7. 鏈?zhǔn)讲僮鞯挠梅?/h5>
所以饺谬,從表面上看捂刺,Promise只是能夠簡(jiǎn)化層層回調(diào)的寫法,而實(shí)質(zhì)上募寨,Promise的精髓是“狀態(tài)”族展,用維護(hù)狀態(tài)、傳遞狀態(tài) 的方式來(lái)使得回調(diào)函數(shù)能夠及時(shí)調(diào)用拔鹰,它比傳遞callback函數(shù)要簡(jiǎn)單仪缸、靈活的多。所以使用Promise的正確場(chǎng)景是這樣的:
new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: function (data) {
// console.log(data)
res(data);
},
error: function () {
rej()
}
})
})
.then((data) => {
console.log(data)
return new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/2',
success: function (data) {
res(data)
},
error: function () {
rej()
}
})
})
})
.then((data) => {
console.log(data);
return new Promise((res,rej)=>{
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
success: function (data) {
console.log(data)
}
})
})
})
1.8. resolve與reject方法
1.8.1 Promise.resolve()
有時(shí)需要將現(xiàn)有對(duì)象轉(zhuǎn)為 Promise 對(duì)象列肢,Promise.resolve方法就起到這個(gè)作用恰画。
// Promise構(gòu)造函數(shù)上提供的靜態(tài)方法resolve, rejec
let num =50; //將一個(gè)值轉(zhuǎn)成成功的狀態(tài)
let promise = Promise.resolve(num)//構(gòu)造函數(shù)上提供一個(gè)靜態(tài)方法
console.log(promise); // 成功后的狀態(tài),值為50
promise
.then(data=>console.log(data))
const jsPromise = Promise.resolve('123');
上面代碼將123轉(zhuǎn)為一個(gè) Promise 對(duì)象瓷马。
Promise.resolve等價(jià)于下面的寫法拴还。
Promise.resolve('123')
// 等價(jià)于
new Promise(resolve => resolve('123'))
Promise.resolve`方法的參數(shù)分成四種情況。
1欧聘、參數(shù)是一個(gè) Promise 實(shí)例
如果參數(shù)是 Promise 實(shí)例片林,那么Promise.resolve將不做任何修改、原封不動(dòng)地返回這個(gè)實(shí)例。
let promise = new Promise(res=>res(50)) //構(gòu)造函數(shù)創(chuàng)建一個(gè)Promise對(duì)象费封,成功狀態(tài)
console.log(promise);
let pro = Promise.resolve(promise)
console.log(pro === promise); //兩個(gè)對(duì)象是同一個(gè)對(duì)象
pro.then(data=>console.log(data))// 通過(guò)兩個(gè)對(duì)象拿到的數(shù)據(jù)是一樣的
promise.then(data=>console.log(data))
2焕妙、參數(shù)是一個(gè)thenable對(duì)象
thenable對(duì)象指的 是具有then方法的對(duì)象,比如下面這個(gè)對(duì)象孝偎。
Promise.resolve方法會(huì)將這個(gè)對(duì)象轉(zhuǎn)為 Promise 對(duì)象访敌,然后就立即執(zhí)行thenable對(duì)象的then`方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let pro = Promise.resolve(thenable);
console.log(pro);
pro.then(data=>console.log(data))//拿到數(shù)據(jù)
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代碼中衣盾,thenable對(duì)象的then方法執(zhí)行后寺旺,對(duì)象p1的狀態(tài)就變?yōu)閞esolved,從而立即執(zhí)行最后那個(gè)then方法指定的回調(diào)函數(shù)势决,輸出 42阻塑。
3、參數(shù)不是具有then方法的對(duì)象果复,或根本就不是對(duì)象
如果參數(shù)是一個(gè)原始值陈莽,或者是一個(gè)不具有then方法的對(duì)象,則Promise.resolve方法返回一個(gè)新的 Promise 對(duì)象虽抄,狀態(tài)為resolved走搁。
et pro = Promise.resolve('xingyou');
console.log(pro);
pro.then(data=>console.log(data))//拿到數(shù)據(jù)
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
上面代碼生成一個(gè)新的 Promise 對(duì)象的實(shí)例p。由于字符串Hello不屬于異步操作(判斷方法是字符串對(duì)象不具有 then 方法)迈窟,返回 Promise 實(shí)例的狀態(tài)從一生成就是resolved私植,所以回調(diào)函數(shù)會(huì)立即執(zhí)行。Promise.resolve方法的參數(shù)车酣,會(huì)同時(shí)傳給回調(diào)函數(shù)曲稼。
4、不帶有任何參數(shù)
Promise.resolve方法允許調(diào)用時(shí)不帶參數(shù)湖员,直接返回一個(gè)resolved狀態(tài)的 Promise 對(duì)象贫悄。
所以,如果希望得到一個(gè) Promise 對(duì)象娘摔,比較方便的方法就是直接調(diào)用Promise.resolve方法窄坦。
let pro = Promise.resolve();
console.log(pro);
pro.then(data=>console.log(data))//拿到數(shù)據(jù)
1.8.2 Promise.reject()
Promise.reject(reason)方法也會(huì)返回一個(gè)新的 Promise 實(shí)例,該實(shí)例的狀態(tài)為rejected`凳寺。
Promise.reject就是將參數(shù)轉(zhuǎn)為失敗狀態(tài)的內(nèi)容鸭津,返回的也是promise對(duì)象
const p = Promise.reject('出錯(cuò)了');
// 等同于
// const p = new Promise((resolve, reject) => reject('出錯(cuò)了'))
p.then(null, function (s) {
console.log(s)
}); // 出錯(cuò)了
上面代碼生成一個(gè) Promise 對(duì)象的實(shí)例p,狀態(tài)為rejected读第,回調(diào)函數(shù)會(huì)立即執(zhí)行曙博。
注意,Promise.reject()方法的參數(shù)怜瞒,會(huì)原封不動(dòng)地作為reject的理由父泳,變成后續(xù)方法的參數(shù)般哼。這一點(diǎn)與Promise.resolve方法不一致。
const thenable = {
then(resolve, reject) {
reject('出錯(cuò)了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
}) // true
上面代碼中惠窄,Promise.reject方法的參數(shù)是一個(gè)thenable對(duì)象蒸眠,執(zhí)行以后,后面catch方法的參數(shù)不是reject拋出的“出錯(cuò)了”這個(gè)字符串杆融,而是thenable對(duì)象楞卡。
1.9. Promise.all()
promise的all 方法:統(tǒng)一處理成功后的Promise。Promise.all([])統(tǒng)一調(diào)用then方法
all()方法的參數(shù)都是promise對(duì)象
Promise.all([p1,p2,p3])
把promise打包,扔到一個(gè)數(shù)組里面,打包完還是一個(gè)promise對(duì)象
如果是all方法,必須確保,所有的promise對(duì)象,都是resolve狀態(tài),都是成功的狀態(tài),否則就報(bào)錯(cuò)
// 如果p2是reject就會(huì)走catch
let p1 = Promise.resolve("p1成功");
let p2 = Promise.reject("p2"); //只要有一個(gè)失敗就會(huì)走catch方法脾歇,全部成功才走then
let p3 = Promise.resolve("p3成功");
Promise.all([p1,p2,p3])
.then(res => {
console.log(res); // 這里的res是一個(gè)有p1,p2,p3里面的resolve組成的數(shù)組
})
.catch(err=>{
console.log('err',err);
})
1.10 Promise.race()
- promise的race的方法
Promise.race([p1,p2,p3])
這個(gè)和all用法一樣,唯一不同之處就是race方法只要最前面一個(gè)resolve就可以正常執(zhí)行,如果排在前面的是reject就報(bào)錯(cuò)
// 執(zhí)行第一個(gè)狀態(tài)發(fā)生變化的Promise
let p1 = Promise.reject("p1成功");
let p2 = Promise.resolve("p2"); //只要有一個(gè)失敗就會(huì)走catch方法蒋腮,全部成功才走then
let p3 = Promise.resolve("p3成功");
Promise.race([p1,p2,p3])
.then(res => {
console.log(res); // 這里的res是一個(gè)有p1,p2,p3里面的resolve組成的數(shù)組
})
.catch(err=>{
console.log('err',err);
})
race的方法作用
//可以利用race方法的作用來(lái)判斷超時(shí)處理
// 異步處理函數(shù)
function foo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(20)
}, 3000)
})
}
// 封裝超時(shí)函數(shù)
function timeoutPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('超時(shí)')
}, delay)
})
}
Promise.race([
foo(),
timeoutPromise(1000)
]).then(function (res) {
console.log('res', res)
}, function (err) {
console.log('err', err)
})
let p1= new Promise(resolve =>{
setTimeout(() =>{
resolve(123)
},3000)
})
let pp =new Promise(resolve =>{
setTimeout(()=>{
resolve('請(qǐng)求超時(shí)')
},2000)
})
Promise.race([p1,pp])
.then(res =>{
console.log(res);
})
.catch(err => console.log('err',err))
2.generator 生成器
2.1. 基本概念
Generator 生成器是ESMAScript6 一個(gè)重要的特性
執(zhí)行 Generator 函數(shù)會(huì)返回一個(gè)迭代器對(duì)象,也就是說(shuō)藕各,Generator 函數(shù)還是一個(gè)迭代器對(duì)象生成函數(shù)池摧。返回的迭代器對(duì)象,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個(gè)狀態(tài)激况。
生成器,也是一個(gè)函數(shù),
2.1.1 跟普通函數(shù)的區(qū)別
- function關(guān)鍵字與函數(shù)名之間有一個(gè)星號(hào)作彤;
- 函數(shù)體內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)乌逐。
- Generator函數(shù)不能跟new一起使用竭讳,會(huì)報(bào)錯(cuò).
generator函數(shù)一個(gè)一個(gè)處理yield
function * gen(){
yield 10;
yield 20;
yield 30;
return 50; //最后一次拿到return的值。obj.next()執(zhí)行到最后done:true
}
let obj = gen(); //執(zhí)行后返回enerator對(duì)象
console.log(obj);//執(zhí)行后浙踢,會(huì)返回一個(gè)對(duì)象绢慢,對(duì)象上有個(gè)next()方法
console.log(obj.next());//每次調(diào)用next方法,獲取yield后面對(duì)應(yīng)的值
// 當(dāng)done第一次為true是表示generator里面內(nèi)容執(zhí)行完畢,如果還繼續(xù)調(diào)用next方法,返回值為undefined,done依然為true,告訴你執(zhí)行完畢了
generator函數(shù)批量處理yield
let arr = [10, 20, 30, 40, 50, 60, 70]
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let obj = gen(arr);
console.log(obj);
console.log(obj.next());
//報(bào)錯(cuò)寫法
let arr = [10, 20, 30, 40, 50, 60, 70]
function* show(arr) {
arr.forEach(function (item, index) {
yield item // 注意 yield 關(guān)鍵字只能在生成器generator函數(shù)中使用(直屬的),現(xiàn)在在forearch的回調(diào)函數(shù)中
})
}
let obj = gen(arr);
console.log(obj);
generator函數(shù)表達(dá)式
除了可以通過(guò)函數(shù)聲明的方式創(chuàng)建生成器函數(shù), 也可以通過(guò)函數(shù)表達(dá)式創(chuàng)建generator生成器
var show = function * (arr){ //此時(shí)因?yàn)槭悄涿瘮?shù)表達(dá)式, 所以`*`在function 關(guān)鍵字和小括號(hào)之間
for(let i = 0; i< arr.length; i++){
yield arr[i]
}
}
注意:不能通過(guò)箭頭函數(shù)創(chuàng)建生成器
//生成器的目的就是為了創(chuàng)建迭代對(duì)象,創(chuàng)建的迭代器對(duì)象可以使用for of循環(huán)(普通的對(duì)象不能使用for of)for of 就是循環(huán)迭代器對(duì)象的
let arr = [10, 20, 30, 40, 50, 60, 70]
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let obj = gen(arr);
// let obj ={name:'dddd',age :18,like:"讀書(shū)"} //普通的對(duì)象不能使用for of 會(huì)報(bào)錯(cuò)
for(let val of obj){
console.log(val);
}
//會(huì)發(fā)現(xiàn),在使用for..of.. 遍歷的時(shí)候,不會(huì)遍歷return后面的內(nèi)容
// 生成的迭代器對(duì)象有迭代器成黄,所以也可以解構(gòu)
let arr = [10, 20, 30, 40, 50, 60, 70]
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let [a, b, c, d, ...e] = gen()
console.log(a, b, c, d, e);
console.log(e);
// 生成的迭代器對(duì)象有迭代器呐芥,所以也可以解構(gòu)
let arr = ['hello', 'world'];
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let [a, b] = gen();
console.log(a, b);
let arr = [10, 20, 30, 40, 50, 60, 70]
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let newArr = [...gen(arr)]
console.log(newArr == arr);
console.log(newArr);
// Array.from(gen()) 創(chuàng)建數(shù)組
let arr = [10, 20, 30, 40, 50, 60, 70]
function* gen() {
for (let i = 0; i < arr.length; i++) {
yield arr[i]
}
}
let newArr = [Array.from(gen())]
console.log(newArr == arr);
console.log(newArr);
2.4 對(duì)象生成器方法
由于生成器本身就是函數(shù), 因而可以添加到對(duì)象中, 成為對(duì)象的方法
let obj ={
createIterator:function * (arr){
for(let i = 0; i< arr.length;i++){
yield arr[i]
}
}
}
let iterator = obj.createIterator([10,20,30]) // 創(chuàng)建迭代器對(duì)象
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//也可以用ES6 對(duì)象方法簡(jiǎn)寫方式來(lái)創(chuàng)建生成器, 只需要在函數(shù)名前添加一個(gè)星號(hào)(*)
let obj ={
*createIterator(arr){
for(let i = 0; i< arr.length;i++){
yield arr[i]
}
}
}
let iterator = obj.createIterator([10,20,30]) // 創(chuàng)建迭代器對(duì)象
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//利用生成器給普通對(duì)象寫一個(gè)迭代器,對(duì)象就可以使用for of了
let obj = {
*[Symbol.iterator]() { //利用生成器給對(duì)象寫一個(gè)迭代器
yield 10;
yield 20;
yield 30;
yield 40;
yield 50
}
}
// for(let val of obj){
// console.log(val); // 普通對(duì)象不能使用for of逻杖,會(huì)報(bào)錯(cuò)
// }
for (let val of obj) { //for of會(huì)調(diào)用對(duì)象的迭代器奋岁,可以利用生成器給對(duì)象寫一個(gè)迭代器
console.log(val);
}
具有Symbol.iterator方法的對(duì)象,通過(guò)這個(gè)方法可以創(chuàng)建一個(gè)迭代器對(duì)象.因此所有通過(guò)生成器創(chuàng)建迭代器都是迭代對(duì)象, 諸如字符串, 數(shù)組,Set,Map ,都默認(rèn)具有迭代器暗赶。
而for...of 循環(huán)的本質(zhì)就是通過(guò)每次調(diào)用迭代對(duì)象的next()方法, 并將迭代器返回的 結(jié)果對(duì)象中的value屬性值存到一個(gè)變量中, 循環(huán)執(zhí)行直到結(jié)果對(duì)象中done屬性值為true為止
let arr = [10,20,30]
for(let num of arr){
console.log(num)
}
//傳參
function * show(){
let a =yield 10 //可以把yield看成斷點(diǎn) 返回的值{value:10,done:false}
console.log(a);
let b = yield a+20 //第二個(gè)斷點(diǎn)毙驯,返回{value:30,done:false}
console.log(b);
}
let obj =show()
console.log(obj);
console.log(obj.next())
console.log(obj.next(10)) //把返回的值賦值給a
console.log(obj.next(15)) //傳一個(gè)15進(jìn)去,b就是15线得。沒(méi)有yield 返回{value: undefined, done: true}
2.5 generator生成器處理異步
2.5.1 處理本地異步程序
//一個(gè)本地的異步程序
function asyncFun(num){
return function(cb){
setTimeout(function(){
cb(num) //3够话、cb中的函數(shù)體執(zhí)行蓝翰,使用num的值
},3000)
}
}
let fn = asyncFun(10); //1、執(zhí)行結(jié)果返回一個(gè)函數(shù)體
fn(function(val){ //2女嘲、返回的函數(shù)執(zhí)行畜份,參數(shù)是一個(gè)函數(shù),被cb接收
console.log(val);
})
//generator處理異步程序
function asyncFun(num) {
return function (cb) {
setTimeout(function () {
cb(num) //3欣尼、cb中的函數(shù)體執(zhí)行爆雹,使用num的值
}, 3000)
}
}
//封裝一個(gè)處理異步的函數(shù)
function run(generator) {
let obj = generator() //通過(guò)生成器創(chuàng)建迭代器對(duì)象
console.log(obj); //迭代器對(duì)象原型上有個(gè)next方法
let result = obj.next();
console.log(result);//next方法每次執(zhí)行都會(huì)返回結(jié)果對(duì)象
function step() { //采用遞歸判斷next是否執(zhí)行完
if (!result.done) {
result = obj.next();
console.log(result);
step() //遞歸調(diào)用
}
}
step() //先執(zhí)行一次
}
run(
function* () { //傳一個(gè)匿名生成器函數(shù)
yield 10;
yield 20
yield 30
})
//如何讓異步程序與迭代函數(shù)掛鉤
function asyncFun(num) {
return function (cb) {
setTimeout(function () {
cb(num)
}, 3000)
}
}
function run(generator) {
let obj = generator()
console.log(obj); //通過(guò)生成器創(chuàng)建迭代器對(duì)象
let result = obj.next(); //迭代器對(duì)象原型上有個(gè)next方法
console.log(result); //next方法每次執(zhí)行都會(huì)返回結(jié)果對(duì)象
function step() {
if (!result.done) {
if (typeof result.value === 'function') { //value是否為函數(shù)
result.value(function (val) { //執(zhí)行value的是return出來(lái)的函數(shù)停蕉,且要傳一個(gè)回調(diào)函數(shù)給參數(shù)cb,回調(diào)函數(shù)cb三秒以后執(zhí)行
console.log(val);
result = obj.next(val); //返回下次執(zhí)行的結(jié)果對(duì)象
console.log(result);
step()
})
//每次都會(huì)返回結(jié)果對(duì)象{value:,done:},當(dāng)done為true是value為undefined,undefined沒(méi)有value屬性
}
}
}
step()
}
run(
function* () {
let res = yield asyncFun(10); //將yield 10換成yield asyncFun(10)實(shí)現(xiàn)與異步程序掛鉤钙态,此時(shí)返回的結(jié)果對(duì)象中的value的值就為一個(gè)函數(shù)
res = yield asyncFun(res + 10)
res = yield asyncFun(res + 10)
console.log(res);
})
2.5.2 處理ajax程序
//復(fù)用ajax的異步函
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function asyncFun(url) { //generator 發(fā)送ajax的異步函數(shù) 參數(shù)換成url
return function (cb) { //本地定時(shí)器不要了慧起,換成ajax請(qǐng)求
$.ajax({
url, //對(duì)象屬性簡(jiǎn)寫方式
success(data) { //向后臺(tái)發(fā)送的數(shù)據(jù)請(qǐng)求成功了把數(shù)據(jù)傳給data
cb({
iserr: 0, //0表示沒(méi)有報(bào)錯(cuò)
data,
})
},
error(err) {
cb({
iserr: 1,
data: err, // 錯(cuò)誤信息
})
}
})
}
}
let fn = asyncFun('https://jsonplaceholder.typicode.com/todos/1') // 發(fā)送ajax的異步函數(shù)執(zhí)行,返回return的函數(shù)
let fn2 = asyncFun('https://jsonplaceholder.typicode.com/todos/2') //復(fù)用ajax請(qǐng)求函數(shù)asyncFun册倒,減少代碼量蚓挤,只傳url
fn(function (result) {//返回的這個(gè)函數(shù)執(zhí)行時(shí),會(huì)接收一個(gè)回調(diào)函數(shù)
if (!result.iserr) {
console.log('請(qǐng)求成功');
console.log(result.data);
} else {
console.log('請(qǐng)求失敗');
}
})
fn2(function (result) {//返回的這個(gè)函數(shù)執(zhí)行時(shí)驻子,會(huì)接收一個(gè)回調(diào)函數(shù)
if (!result.iserr) {
console.log('請(qǐng)求成功');
console.log(result.data);
} else {
console.log('請(qǐng)求失敗');
}
})
<!-- generator通過(guò)封裝處理異步ajax請(qǐng)求 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function asyncFun(url) { //generator 發(fā)送ajax的異步函數(shù) 參數(shù)換成url
return function (cb) { //本地定時(shí)器不要了灿意,換成ajax請(qǐng)求
$.ajax({
url, //對(duì)象屬性簡(jiǎn)寫方式
success(data) { //向后臺(tái)發(fā)送的數(shù)據(jù)請(qǐng)求成功了把數(shù)據(jù)傳給data
cb({
iserr: 0, //0表示沒(méi)有報(bào)錯(cuò)
data,
})
},
error(err) {
cb({
iserr: 1,
data: err, // 錯(cuò)誤信息
})
}
})
}
}
function run(generator) {
let obj = generator()
console.log(obj); //通過(guò)生成器創(chuàng)建迭代器對(duì)象
let result = obj.next(); //迭代器對(duì)象原型上有個(gè)next方法
console.log(result); //next方法每次執(zhí)行都會(huì)返回結(jié)果對(duì)象
function step() {
if (!result.done) {
if (typeof result.value === 'function') { //value是否為函數(shù)
result.value(function (val) {
console.log(val);
result = obj.next(val);
step()
})
}
}
}
step()
}
run(//下載代碼層面已經(jīng)看不出嵌套了
function* () {
let result = yield asyncFun('https://jsonplaceholder.typicode.com/todos/1'); //傳url
console.log('result', result);
if (!result.iserr) {
console.log('請(qǐng)求成功');
console.log(result.data);
} else {
console.log('請(qǐng)求失敗');
}
result = yield asyncFun('https://jsonplaceholder.typicode.com/todos/' + (result.data.id + 1));
console.log('result', result);
if (!result.iserr) {
console.log('請(qǐng)求成功');
console.log(result.data);
} else {
console.log('請(qǐng)求失敗');
}
result = yield asyncFun('https://jsonplaceholder.typicode.com/todos/' + (result.data.id + 1));
console.log('result', result);
if (!result.iserr) {
console.log('請(qǐng)求成功');
console.log(result.data);
} else {
console.log('請(qǐng)求失敗');
}
})
</script>
<!-- generator結(jié)合promise 處理異步程序簡(jiǎn)單分析 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function* show() {
yield new Promise((resolve, reject) => {
resolve(10) //這里如果調(diào)用了resolve,后面的then方法就會(huì)拿到data數(shù)據(jù)10
})
yield new Promise((resolve, reject) => { //如果還有第二個(gè)yield
resolve(200)
})
}
let gen = show(); //生成器對(duì)象
let a = gen.next(); //結(jié)果對(duì)象{value: Promise, done: false}崇呵。第一次調(diào)用next()時(shí)脾歧,程序終止在yield后面,能夠拿到值演熟,表示定義一個(gè)promise已經(jīng)執(zhí)行完了鞭执,就可以執(zhí)行第二次的generator了
a.value.then( //結(jié)果對(duì)象的值是Promise就可以使用then方法
(data) => {
console.log(data); //第一次的結(jié)果
return gen.next().value //第二次的generator的值是也promise對(duì)象,取出來(lái)芒粹,然后return出去
}
).then(((aa) => {
console.log(aa); //拿到第二次的值
}))
</script>
<!-- 三個(gè)平級(jí)的請(qǐng)求結(jié)合promise 處理異步程序 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function* show() {
yield new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: resolve,
error: reject
})
})
yield new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/2',
success: resolve,
error: reject
})
})
yield new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/3',
success: resolve,
error: reject
})
})
}
let gen = show();
gen.next()
.value
.then(function (data) { //then方法第一個(gè)值是數(shù)據(jù)
console.log(data);
return gen.next().value
})
.then(
data => {
console.log(data);
return gen.next().value
}
)
.then(
data => {
console.log(data);
}
)
</script>
<!-- 遞歸嵌套請(qǐng)求結(jié)合promise 處理異步程序 兄纺,拿到第一次的值發(fā)送第二次請(qǐng)求,拿到第二次發(fā)送第三次的請(qǐng)求-->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function* show() {
let id = yield new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: resolve,
error: reject
})
})
id = yield new Promise(
(resolve, reject) => {
$.ajax({
url: `https://jsonplaceholder.typicode.com/todos/${id + 2}`, //id是基于上次的id加2
success: resolve,
error: reject
})
})
id = yield new Promise(
(resolve, reject) => {
$.ajax({
url: `https://jsonplaceholder.typicode.com/todos/${id + 2}`,
success: resolve,
error: reject
})
})
}
let gen = show();
gen.next()
.value
.then(function (data) { //then方法第一個(gè)值是數(shù)據(jù)
console.log(data);
let { id } = data;
console.log(id)
return gen.next(id).value //id拿到后可以作為下一次的參數(shù) 化漆,也就是yield的結(jié)果會(huì)返回一個(gè)id
})
.then(
data => {
console.log(data);
let { id } = data;
console.log(id)
return gen.next(id).value
}
)
.then(
data => {
console.log(data);
let { id } = data;
console.log(id)
}
)
</script>
<!-- async實(shí)際工作中使用異步函數(shù),async函數(shù)中代碼好像被拉平了(一行異步一行同步) -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
async function show() { //*去掉估脆,前面加async yield換成await,定義個(gè)變量拿到結(jié)果
try { //避免出錯(cuò),還要捕獲一下
let result1 = await new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: resolve,
error: reject
})
})
console.log('result1', result1);
let result2 = await new Promise( //之前的程序是先同步后異步座云。有了await以后不斷的等待異步結(jié)果疙赠,再執(zhí)行同步
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/2',
success: resolve,
error: reject
})
})
console.log('result2', result2);
let result3 = await new Promise(
(resolve, reject) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/3',
success: resolve,
error: reject
})
})
console.log('result3', result3);
} catch (err) { console.log(err); }
}
show()
<!-- async函數(shù)的請(qǐng)求函數(shù)還可以封裝,代碼更加優(yōu)雅 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function request(url) { //封裝請(qǐng)求函數(shù) 參數(shù)為url
//會(huì)返回一個(gè)Promise
return new Promise(
(resolve, reject) => {
$.ajax({
url,
success: resolve,
error: reject
})
})
}
async function show() {
try {
let result1 = await request('https://jsonplaceholder.typicode.com/todos/1')
console.log('result1', result1);
let result2 = await request('https://jsonplaceholder.typicode.com/todos/2')
console.log('result2', result2);
let result3 = await request('https://jsonplaceholder.typicode.com/todos/3')
console.log('result3', result3);
} catch (err) { console.log(err); }
}
show()
<!-- async函數(shù)的請(qǐng)求函數(shù)還可以封裝朦拖,代碼更加優(yōu)雅 id還可以使用上一次的值得到 -->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function request(url) {
return new Promise(
(resolve, reject) => {
$.ajax({
url,
success: resolve,
error: reject
})
})
}
async function show() {
try {
let result1 = await request('https://jsonplaceholder.typicode.com/todos/1')
console.log('result1', result1);
let id = result1.id; //id還可以使用上一次的值得到
let result2 = await request(`https://jsonplaceholder.typicode.com/todos/${id+2}`)
console.log('result2', result2);
id = result2.id;
let result3 = await request(`https://jsonplaceholder.typicode.com/todos/${id+2}`)
console.log('result3', result3);
} catch (err) { console.log(err); }
}
show()
</script>
<!-- 帶await的異步函數(shù)對(duì)象調(diào)用圃阳,需要在函數(shù)前面加上async ,否則報(bào)錯(cuò)-->
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js'></script>
<script>
function request(url) {
return new Promise(
(resolve, reject) => {
$.ajax({
url,
success: resolve,
error: reject
})
})
}
let obj = {
async show() { //這種es6對(duì)象方法的簡(jiǎn)寫方式會(huì)報(bào)錯(cuò)璧帝,因?yàn)閍wait必須在async函數(shù)里捍岳,所以在前面加上async
// show: async function show(){ //這是es5帶await對(duì)象方法寫法
try {
let result1 = await request('https://jsonplaceholder.typicode.com/todos/1')
console.log('result1', result1);
let id = result1.id; //id還可以使用上一次的值得到
let result2 = await request(`https://jsonplaceholder.typicode.com/todos/${id + 2}`)
console.log('result2', result2);
id = result2.id;
let result3 = await request(`https://jsonplaceholder.typicode.com/todos/${id + 2}`)
console.log('result3', result3);
} catch (err) { console.log(err); }
},
}
obj.show() //帶await的異步函數(shù)對(duì)象調(diào)用