第二十九節(jié): ES6 generator 與 Promise

  //之前的異步程序定時(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í)行棧
yb.jpg
      //想個(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)
  1. promise對(duì)象的狀態(tài)不受外界影響沾谓。
  2. 一旦狀態(tài)改變,就不會(huì)再變戳鹅,任何時(shí)候都可以得到這個(gè)結(jié)果均驶。
1.3. 狀態(tài)

Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):

  1. pending(進(jìn)行中)枫虏、 此時(shí)操作尚未完成
  2. fulfilled(resolve)(已成功) 異步操作成功
  3. rejected(reject)(已失敻狙ā)。 異步操作失敗

只有異步操作的結(jié)果隶债,可以決定當(dāng)前是哪一種狀態(tài)腾它,任何其他操作都無(wú)法改變這個(gè)狀態(tài)。

1.4.缺點(diǎn)
  1. 無(wú)法取消Promise死讹,一旦新建它就會(huì)立即執(zhí)行携狭,無(wú)法中途取消。
  2. 如果不設(shè)置回調(diào)函數(shù)回俐,Promise內(nèi)部拋出的錯(cuò)誤逛腿,不會(huì)反應(yīng)到外部稀并。
  3. 當(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()
  1. 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ū)別

  1. function關(guān)鍵字與函數(shù)名之間有一個(gè)星號(hào)作彤;
  2. 函數(shù)體內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)乌逐。
  3. 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)用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市睬隶,隨后出現(xiàn)的幾起案子锣夹,更是在濱河造成了極大的恐慌,老刑警劉巖苏潜,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件银萍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恤左,警方通過(guò)查閱死者的電腦和手機(jī)贴唇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門贰锁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人滤蝠,你說(shuō)我怎么就攤上這事豌熄。” “怎么了物咳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵锣险,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我览闰,道長(zhǎng)芯肤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任压鉴,我火速辦了婚禮崖咨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘油吭。我一直安慰自己击蹲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布婉宰。 她就那樣靜靜地躺著歌豺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪心包。 梳的紋絲不亂的頭發(fā)上类咧,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音蟹腾,去河邊找鬼痕惋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛娃殖,可吹牛的內(nèi)容都是我干的值戳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼珊随,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼述寡!你這毒婦竟也來(lái)了柿隙?” 一聲冷哼從身側(cè)響起叶洞,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎禀崖,沒(méi)想到半個(gè)月后衩辟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡波附,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年艺晴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昼钻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡封寞,死狀恐怖然评,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狈究,我是刑警寧澤碗淌,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站抖锥,受9級(jí)特大地震影響亿眠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜磅废,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一纳像、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拯勉,春花似錦竟趾、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至斗遏,卻和暖如春山卦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诵次。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工账蓉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逾一。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓铸本,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親遵堵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子箱玷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容