Promise異步編程

1、什麼是Promise
ajax

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。 所謂Promise,簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果。編程

從語法上說,Promise 是一個對象,從它能夠獲取異步操做的消息。Promise 提供統一的 API,各類異步操做均可以用一樣的方法進行處理。promise

如下是MDN對Promise的定義異步

The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future. async

譯文:Promise對象用於異步操做,它表示一個還沒有完成且預計在將來完成的異步操做。異步編程

2、同步和異步函數

 

咱們知道,JavaScript的執行環境是「單線程」。 spa

所謂單線程,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,也就是一次只能完成一項任務,這個任務執行完後才能執行下一個,它會「阻塞」其餘任務。這個任務可稱爲主線程。 線程

但實際上還有其餘線程,如事件觸發線程、ajax請求線程等。 這也就引起了同步和異步的問題。 對象

同步:

while(true);

console.log("don't execute"); //不會執行

異步:

setTimeout(function() {

    console.log('taskA, asynchronous');

}, 0);

console.log('taskB, synchronize');

3、回調函數

 

回調函數是一段可執行的代碼段,它以「參數」的形式傳遞給其餘代碼,在其合適的時間執行這段(回調函數)的代碼。

var friends = ["Mike", "Stacy", "Andy", "Rick"];

friends.forEach(function (eachName, index){

    console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick

});

 

上面例子中的setTimeout就是一個回調函數

再看一次:

setTimeout(function() {

console.log('taskA, asynchronous');

}, 0);

console.log('taskB, synchronize');

4、爲何使用Promise

 

使用上面的回調函數的方式,若是回調函數嵌套不少層,很容易陷入回調地獄,代碼可讀性差

function fn(callback1, callback2) {

  // 耗時操做 let a = 0

  for (let i = 0; i < 100; i++) {

    a++

  }

  setTimeout(function() {

    callback1(++a)

    setTimeout(function() {

      callback2(++a)

    }, 0)

   }, 0)

}

function fn1(a) {

  console.log(a)

}

function fn2(a) {

  console.log(a)

}

fn(fn1, fn2)

5、Promise基本概念

 

Promise對象表明一個未完成、但預計未來會完成的操做。

ES6 規定,Promise對象是一個構造函數,用來生成Promise實例。

Promise構造函數接受一個函數做爲參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由 JavaScript 引擎提供,不用本身部署。

resolve函數的做用是,將Promise對象的狀態從「未完成」變爲「成功」(即從 pending 變爲 resolved),在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去;

reject函數的做用是,將Promise對象的狀態從「未完成」變爲「失敗」(即從 pending 變爲 rejected),在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。

 

它有如下三種狀態:

pending:初始值,不是fulfilled,也不是rejected

fulfilled:表明操做成功

rejected:表明操做失敗

 

Promise有兩種狀態改變的方式,既能夠從pending轉變爲fulfilled,也能夠從pending轉變爲rejected

一旦狀態改變,就「凝固」了,會一直保持這個狀態,不會再發生變化。

當狀態發生變化,promise.then綁定的函數就會被調用。

注意:Promise一旦新建就會「當即執行」,沒法取消。

6、Promise基本用法

 

下面代碼創造了一個Promise實例。

const promise = new Promise(

  // executor

  function(resolve, reject) {

    if (/* 異步操做成功 */){

      resolve(value);

    } else {

      reject(error);

    }

});

executor是帶有 resolve 和 reject 兩個參數的函數 。Promise構造函數執行時當即調用executor 函數, resolve 和 reject 兩個函數做爲參數傳遞給executor(executor 函數在Promise構造函數返回所建promise實例對象前被調用)。resolve 和 reject 函數被調用時,分別將promise的狀態改成fulfilled(完成)或rejected(失敗)。executor 內部一般會執行一些異步操做,一旦異步操做執行完畢(可能成功/失敗),要麼調用resolve函數來將promise狀態改爲fulfilled,要麼調用reject 函數將promise的狀態改成rejected。

Promise實例生成之後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數。

promise.then(function(value) { // success }, function(error) { // failure }); then方法能夠接受兩個回調函數做爲參數。第一個回調函數是Promise對象的狀態變爲resolved時調用,第二個回調函數是Promise對象的狀態變爲rejected時調用。其中,第二個函數是可選的,不必定要提供。這兩個函數都接受Promise對象傳出的值做爲參數。

7、Promise實例應用

 

//簡單的promise
const promise1 = new Promise(
  // executor
  function(resolve, reject) {
    if (false){
      resolve('request success');
    } else {
      reject('request error');
    }
});
promise.then(function(value) {
  console.log(value);
}, function(error) {
  console.log(error);
});

//then只傳一個方法的狀況
const promise2 = new Promise(
// executor
function(resolve, reject) {
if (false){
resolve('request success');
} else {
reject('request error');
}
});
promise2.then(function(value) {
console.log(value);
});
promise2.catch(function(error) {
console.log(error);
});

//鏈式調用
const promise3 = new Promise(
  // executor
  function(resolve, reject) {
    if (false){
      resolve('request success');
    } else {
    reject('request error');
    }
}).then(function(value) {
  console.log(value);
}).catch(function(error) {
  console.log(error);
});

//嵌套調用
const promise4 = new Promise(
  // executor
  function(resolve, reject) {
  if (true){
    resolve('request success');
  } else {
    reject('request error');
  }
}).then(function(value) {
  const nextPromise = new Promise(
    function(resolve, reject) {
      resolve('next request success');
   });
  return nextPromise;
}).then(function(value) {
  console.log(value);
}).catch(function(error){
  console.log(error);
});

相關文章
相關標籤/搜索