天天看點

promise解決回調地獄

回調地獄demo

function getData({ url, success }) {
      const xhr = new XMLHttpRequest()
      xhr.open('get', url)
      xhr.onreadystatechange = function () {
        if (this.readyState === 4) {
          // 加載完成
          const d = JSON.parse(xhr.responseText);
          success(d)
        }
      }
      xhr.send()
    }
getData({
            url:'http://localhost:3000/get',
            success: (data)=>{
                getData({
                    url:'http://localhost:3000/getCategory?id='+data[0].id,
                    success: data => {
                        getData({
                            url:'http://localhost:3000/getNews?id='+data[0].id,
                            success: data => {
                                console.log(data)
                        }
                    })
                }
            })
        }})
      

promise的基本使用

  1. 構造器必須要定一個參數,如果不給就是報錯.例如,new promise()報錯資訊就是:Promise resolver undefined is not a function這不是一個函數
  2. 構造器的實參是一個函數,這個函數的特殊在于他有兩個形參
  3. 在函數的内部,一般會執行異步代碼,然後根據情況來調用
var p1 = new Promise(function(resolve,reject){
     //異步操作 resolve(obj1)  或者 reject(obj2)
});
p1.then(function(rs){
    // 如果p1的狀态是resolved,則then中的函數
    //會執行,且obj1的值會傳給rs
}).catch(function(rs){
    // 如果p1的狀态是reject,則catch中的函數
    //    會執行,且obj2的值會傳給rs
}).finally(function(){
    // 一定會執行的函數
})
      

三種狀态和值

promise的三種狀态

pending:待定剛剛開始一個初始狀态

resolved:成功表示承諾的東西實作了從pending狀态到了resolved

rejected :表示承諾的東西失敗了沒有實作

三種狀态的轉換

pending----resolve----resolved

pending----reject----rejected

三種狀态轉換是不可逆的

使用promise改造回調函數

  1. 第一步:建立模闆.這裡的末班是指固定的套路:寫一個空函數,在函數體中建立一個promise對象并傳回
  2. 第二步:把一部功能寫入構造器中,根據實際來決定是否調用resolve,reject
  3. 第三步:調用函數通過fnName().then().catch()結構來調用這個函數

改寫上面的代碼

function getDataPromise(url) {
      let p = new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open('get', url)
        xhr.onreadystatechange = function () {
          if (this.readyState === 4) {
            // 加載完成
            const d = JSON.parse(xhr.responseText);
            resolve(d)
          }
        }
        xhr.send()
      })
      return p
    }
      

then的格式及執行邏輯

p.then(函數1[,函數2])

第一個參數是resolved狀态回調函數

第二個是rejected狀态的回調函數

執行邏輯

  1. 如果promise對象的狀态是resolved,則then()會執行第一個函數,并傳入目前的PromiseValue
  2. 如果promise對象的狀态是rejected,則then()會執行第二個函數,并傳入目前的PromiseValue
  3. 特别地,如果promise對象的狀态是rejected,且此時then方法并沒有設定第二個參數,就會向外抛出一個錯誤,錯誤的提示大約是Uncaught (in promise)

catch的格式及用法

catch 是 then(null, reject)的别名

一般與then一塊使用,單獨使用無意義

async-await的文法

async,await是es7中的新增文法,用來改進異步代碼寫法,是promise更新版
  1. async函數傳回一個promise對象
  2. async函數内部return語句傳回的值是promise對象的值

await指令

  1. await的外層函數必須有一個async
  2. 正常情況下,await指令後面是一個promise對象,傳回該promise的值.如果不是promise對象就直接傳回對應的值

使用async來優化回調地獄

async function fn() {
      const res = await getDataPromise('http://localhost:3000/get')
      console.log('第1次成功', res)
      const res1 = await getDataPromise('http://localhost:3000/getCategory?id=' + res[0].id)
      console.log('第2次成功', res1)
      const res2 = await getDataPromise('http://localhost:3000/getNews?id=' + res1[0].id)
      console.log('第3次成功', res2)
    }
    fn()