1. 程式人生 > 其它 >javascript Promise

javascript Promise

回撥函式

對比-普通函式和非同步函式返回值

  1. 普通函式的直接返回想要的資料,可以非同步函式不行,於是便有了回撥函式.

進化-回撥函式

例子1

  1. 以前是我希望呼叫你這個函式,然後能夠給我返回一些資料,在我這裡進行處理,但是我拿不到資料
  2. 現在呢,我呼叫你這個函式,感覺我把怎麼處理這些資料的流程都告訴你了,然後在你那裡處理資料吧.
  3. 或者這樣理解,以前,資料的處理流程和執行流程都在我這裡
  4. 現在,我把資料的處理流程告訴你,然後在你那裡進行執行

例子2

  1. 如果requestData()是個普通函式,也就是裡面沒有非同步程式碼,那麼我在20行呼叫這個函式,就是希望這個函式能夠返回某個結果來讓我進行處理.

  2. 但是因為這個requestData()是個非同步請求函式,所以我直接去呼叫這個函式,他並不是立刻馬上就返回一些結果給我,然後進行後續的資料處理.

  3. 所以我傳遞兩個回撥函式給他,然後讓他執行.

  4. 存在的缺點:

    1. 就是不熟悉這個函式的,需要查閱api文件,才能夠使用這個函式,很麻煩
    2. 互動不是很友好

進化-Promise

  1. 非同步函式,返回資料時,返回的資料都是空的.
  2. 於是出現了回撥函式,不要非同步函式返回資料了.
  3. 現在,出現了一個"承諾",非同步函式不返回具體的資料了,而是返回一個"承諾"
  4. 然後我根據這個"承諾"的狀態,來決定做哪種處理

02_Promise.js

function requestData() {
  return new Promise((resolve, reject) => {
    resolve('這是--成功--返回的資料');
    // reject('這是--失敗--返回的資料');
  });
}

const promise = requestData();
promise.then(
  (result) => {
    console.log(result);
  },
  (reason) => {
    console.log(reason);
  }
);

成功的回撥

失敗的回撥

簡寫形式-Promise

Promise的承諾移交

通過resolve移交_看後面

  1. 沒執行,時因為這個newPromise的狀態時Pending狀態.
  1. 執行了,是因為這個新承諾的狀態變成Resolved

  2. 簡單總結:

    1. 執行哪個函式取決於新的承諾

04_Promise_引數也是Promise_resolve移交.js

const newPromise = new Promise((resolve, reject) => {
  resolve('承諾被移交給我啦');
});

new Promise((resolve, reject) => {
  resolve(newPromise);
  // reject('這是--失敗--返回的資料');
}).then(
  (result) => {
    console.log(result);
  },
  (reason) => {
    console.log(reason);
  }
);

通過reject移交_註定失敗

  1. 通過reject移交的承諾,無論後邊的承諾怎麼變化,最後的結果是都時是失敗的承諾

05_Promise_引數也是Promise_reject移交.js

const newPromise = new Promise((resolve, reject) => {
  resolve('承諾被移交給我啦');
  // reject('承諾被移交給我啦,但是沒有兌現');
});

new Promise((resolve, reject) => {
  // resolve(newPromise);
  reject(newPromise);
}).then(
  (result) => {
    console.log('result:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
    console.log(result);
  },
  (reason) => {
    console.log('reason:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
    console.log(reason);
  }
);

通過then方法移交_看後面

  1. 前面的都是傳入一個Promsie來進行承諾移交
  2. 其實也是可以傳入一個包含then方法的物件,來進行狀態移交
  3. 那麼這個"承諾"的狀態則取決於這個then方法裡面的成功或失敗

06_Promise_引數也是Promise_then方法移交.js

const obj = {
  then: function (resolve, reject) {
    // resolve('這個then方法中的成功承諾');
    reject('這個then方法中的失敗承諾');
  },
};
new Promise((resolve, reject) => {
  resolve(obj);
  // reject(obj);
}).then(
  (result) => {
    console.log('result:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
    console.log(result);
  },
  (reason) => {
    console.log('reason:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓');
    console.log(reason);
  }
);

輸出效果

Promise中的立即執行和延後執行

立即執行

  1. 傳入Promise()括號的函式都是立即執行的

延後執行

  1. Promise().then()後面的then裡面傳入的函式不是立即執行,要等待"承諾"的狀態

Promise的多次呼叫

  1. 同一個Promise物件,呼叫多次then方法,則每個then方法都會執行一次

Promise中then方法的鏈式呼叫↓↓↓↓↓↓↓↓

then方法的返回值

  1. 如果你返回的是一個普通的物件,比如字串,數字,物件等等,系統會自動將其轉換成一個Promise,然後這個普通的物件作為resolve()的引數
  2. 當然你也可以直接返回一個Promise物件,上面可以認為是一種語法糖形式
  3. 其次就是要區分,Promise的多次呼叫和鏈式呼叫
    1. 多次呼叫:同一個Promise物件,多次呼叫then方法
    2. 鏈式呼叫:原來的Promise物件,只調用一次then方法,後面的then方法,是由前面的then方法產生的新的Promise物件來呼叫的.

Promise中的的catch方法

  1. 可以捕獲前面的then方法中新生成的promise的"失敗承諾"
  1. 也可以捕獲原始的Promise物件的"失敗承諾"
  2. 也就是說,建立一個Promise物件之後,然後採用鏈式呼叫then()方法,不論呼叫多少次,這個catch方法都會從第一個承諾開始捕獲"失敗的承諾",如果其中有一個"失敗承諾",就是會捕獲到

類方法Promise.resolve()

傳入一個普通物件

  1. 可以將一個普通物件轉換成promise
  2. 和使用new Promise((resolve,reject)=>{ resolve([普通物件])})的效果是一樣的

傳入一個Promise物件

成功的Promise

失敗的Promise

類方法Promise.reject()

  1. 即使傳入一個成功的承諾,也是跳到catch裡面執行,
  2. 因此,可以把Promise.reject()裡面的東西當作字串來進行處理.

類方法Promise.all()

  1. Promise.all()要等號前面的三個promise物件都變成fullfilled,再拿到結果
  1. 在數組裡面放上三個promise物件,當然,也可以放上普通物件,這個時候,他會將這個普通物件轉換成Promise物件,然後和前面的內容引數,拼接成一個數組

15_Promise.all()方法.js

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('1111');
  }, 1000);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('2222');
  }, 1000);
});

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('3333');
  }, 1000);
});

Promise.all([p1, p2, p3, '4444']).then((res) => {
  console.log('res:   ' + res);
});

  1. 只要其中有一個是reject,那麼就是執行catch
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('1111');
  }, 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve('2222');
    reject('2222');
  }, 1000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('3333');
  }, 1000);
});
Promise.all([p1, p2, p3, '4444'])
  .then((res) => {
    console.log('res:   ' + res);
    console.log(res);
  })
  .catch((reason) => {
    console.log('resason:  ' + reason);
  });

類方法Promise.allSettled()

  1. 這個方法要和Promise.all()區分開來
    1. Promise.all()是隻要遇到一個失敗的承諾,就會返回
    2. Promise.allSettled()不管你其中有沒有失敗的承諾,等你全部的承諾都是執行完畢,再返回
    3. 所以Promise.allSettled()中,可以看到所有promise的狀態

16_Promise.allSettled()方法.js

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('1111');
  }, 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve('2222');
    reject('2222');
  }, 1000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('3333');
  }, 1000);
});
Promise.allSettled([p1, p2, p3, '4444'])
  .then((res) => {
    console.log(res);
  })
  .catch((reason) => {
    console.log(reason);
  });

類方法Promise.race()

  1. race這個詞有比賽,賽跑的意思
  2. 所以,故名顧名思義,前面三個promise物件,誰先完成,就結束返回

類方法Promise.any()

  1. 前面三個Promise物件中,至少有一個是resolve的,就會fullfilled
  1. 如果前面三個Promise物件,全部都是reject,最終才會rejected