promise進修筆記

本文我是在進修阮一峰先生的ECMAScript 6 入門的Promise章節時,為了加深影象,通篇都是照抄原文的。
原文地點:阮一峰ECMAScipt入門

1.Promise的寄義

(1)Promise對象代表一個異步操縱,有三種狀況:pending(進行中)、fulfilled(已勝利)和rejected(已失利)。只需異步操縱的效果,能夠決議當前是哪種狀況,任何其他操縱都沒法轉變這個狀況。
(2)一旦狀況轉變,就不會再變,任何時候都能夠取得這個效果。Promise對象的狀況轉變,只需兩種能夠:從pending變成fulfilled和從pending變成rejected。只需這兩種狀況發作,狀況就凝結了,不會再變了,會一向堅持這個效果,這時候就稱為 resolved(已定型)。假如轉變已發作了,你再對Promise對象增加回調函數,也會馬上取得這個效果。這與事宜(Event)完整差別,事宜的特點是,假如你錯過了它,再去監聽,是得不到效果的。
有了Promise對象,就能夠將異步操縱以同步操縱的流程表達出來,避免了層層嵌套的回調函數。別的,Promise對象供應一致的接口,使得掌握異步操縱越發輕易。

Promise也有一些瑕玷。起首,沒法作廢Promise,一旦新建它就會馬上實行,沒法半途作廢。其次,假如不設置回調函數,Promise內部拋出的毛病,不會迴響反映到外部。第三,當處於pending狀況時,沒法得知現在願望到哪個階段(剛剛開始照樣行將完成)。

2、基礎用法

ES6 劃定,Promise對象是一個組織函數,用來天生Promise實例

// 下面代碼製造了一個promise實例
const promise = new Promise(function(resolve, reject) {
    // ...some code
    
    if (/*異步操縱勝利*/) {
        resolve(value);
    } else {
        reject(error)
    }
});

Promise組織函數接收一個函數作為參數,該函數的兩個參數離別是resolve和reject。它們是兩個函數,由JavaScript 引擎供應,不必本身布置。

resolve函數的作用是,將Promise對象的狀況從“未完成”變成“勝利”(即從pending 變成 resolved),在異步操縱勝利時挪用,並將異步操縱的效果作為參數通報出去;reject函數的作用是,將Promise對象的狀況從“未完成”變成“失利”(即從pending 變成 rejected),在異步操縱失利時挪用,並將異步操縱報出的毛病,作為參數通報出去。

Promise實例天生今後,能夠用then要領離別指定resolved狀況和rejected狀況的回調函數。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

then要領能夠接收兩個回調函數作為參數。第一個回調函數是Promise對象的狀況變成resolved時挪用,第二個回調函數是Promise對象的狀況變成rejected時挪用。个中,第二個函數是可選的,不一定要供應。這兩個函數都接收Promise對象傳出的值作為參數。

下面是一個promise對象的簡樸例子:

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done')
    });
}
timeout().then((value) => {
    console.log(value);
})

上面代碼中,timeout要領返回一個Promise實例,示意一段時候今後才會發作的效果。過了指定的時候(ms參數)今後,Promise實例的狀況變成resolved,就會觸發then要領綁定的回調函數。

Promise 新建后就會馬上實行。

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');

上面代碼中,promise 新建后馬上實行,所以起首輸出的是Promise。然後,then要領指定的回調函數,將在當前劇本一切同步任務實行完后才會實行,所以resolved末了輸出。

下面是異步圖片加載的例子:

function loadImageAsync(url) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload = function () {
        resolve(image);
    };
    image.onerror = function() {
        reject(new Error('Could not load image at' + url));
    }
    
    image.src= url;
  })
}

上面代碼中,運用Promise包裝了一個圖片加載的異步操縱。假如加載勝利,就挪用resolve要領,不然就挪用reject要領。

下面是一個用Promise對象完成ajax操縱的例子:

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
  });

  return promise;
};
const getJSon = function(url) {
    const Promise = new Promise(function(resolve, reject){
        const handler = function() {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText));
            }
        };
        
        const client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
    });
   return Promise;
}   
getJSON("/posts.json").then(function(json) {
    console.log('Contents:' + json);
}, function(error) {
    console.log('出錯了', error);
})

上面代碼中,getJSON是對 XMLHttpRequest 對象的封裝,用於發出一個針對 JSON 數據的 HTTP 要求,而且返回一個Promise對象。須要注重的是,在getJSON內部,resolve函數和reject函數挪用時,都帶有參數。

假如挪用resolve函數和reject函數時帶有參數,那末它們的參數會被通報給回調函數。reject函數的參數通常是Error對象的實例,示意拋出的毛病;resolve函數的參數除了平常的值之外,還多是另一個 Promise 實例,比方像下面如許。

const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

上面代碼中,p1和p2都是 Promise 的實例,然則p2的resolve要領將p1作為參數,即一個異步操縱的效果是返回另一個異步操縱。

注重,這時候p1的狀況就會通報給p2,也就是說,p1的狀況決議了p2的狀況。假如p1的狀況是pending,那末p2的回調函數就會守候p1的狀況轉變;假如p1的狀況已是resolved或許rejected,那末p2的回調函數將會馬上實行。

const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error('fail')), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error))
// Error: fail

上面代碼中,p1是一個 Promise,3 秒以後變成rejected。p2的狀況在 1 秒以後轉變,resolve要領返回的是p1。由於p2返回的是另一個 Promise,致使p2本身的狀況無效了,由p1的狀況決議p2的狀況。所以,背面的then語句都變成針對後者(p1)。又過了 2 秒,p1變成rejected,致使觸發catch要領指定的回調函數。

附上本身的明白:p2的狀況在一秒后變成resolve它的參數是p1,所以p2的狀況由p1決議,p1狀況此時是pending,它在三秒后狀況變成rejected,則p2狀況為rejected,所以觸發了catch要領指定的回調函數而不是then要領的。

注重,挪用resolve或reject並不會閉幕 Promise 的參數函數的實行。

new Promise((resolve, reject) => {
  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
// 2
// 1

上面代碼中,挪用resolve(1)今後,背面的console.log(2)照樣會實行,而且會起首打印出來。這是由於馬上 resolved 的 Promise 是在本輪事宜輪迴的末端實行,老是晚於本輪輪迴的同步任務。

平常來說,挪用resolve或reject今後,Promise 的任務就完成了,後繼操縱應當放到then要領內里,而不應當直接寫在resolve或reject的背面。所以,最幸虧它們前面加上return語句,如許就不會有不測。

new Promise((resolve, reject) => {
  return resolve(1);
  // 背面的語句不會實行
  console.log(2);
})

3、Promise.prototype.then()

Promise 實例具有then要領,也就是說,then要領是定義在原型對象Promise.prototype上的。它的作用是為 Promise 實例增加狀況轉變時的回調函數。前面說過,then要領的第一個參數是resolved狀況的回調函數,第二個參數(可選)是rejected狀況的回調函數。

then要領返回的是一個新的Promise實例(注重,不是本來誰人Promise實例)。因而能夠採納鏈式寫法,即then要領背面再挪用另一個then要領。

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});

上面的代碼運用then要領,順次指定了兩個回調函數。第一個回調函數完成今後,會將返回效果作為參數,傳入第二個回調函數。

採納鏈式的then,能夠指定一組根據序次挪用的回調函數。這時候,前一個回調函數,有能夠返回的照樣一個Promise對象(即有異步操縱),這時候后一個回調函數,就會守候該Promise對象的狀況發作變化,才會被挪用。

getJSON("/post/1.json").then(function(post) {
    return getJSON(post.commentURL);
}).then(functon funcA(comments) {
    console.log("resolved:", comments);
}, function funcB(err){
    console.log("rejected:", err);
})

上面代碼中,第一個then要領指定的回調函數,返回的是另一個Promise對象。這時候,第二個then要領指定的回調函數,就會守候這個新的Promise對象狀況發作變化。假如變成resolved,就挪用funcA,假如狀況變成rejected,就挪用funcB。

假如採納箭頭函數,上面的代碼能夠寫得更簡約。

getJSON("/post/1.json").then(
    post => getJSON(post.commentURL)
).then(
    comments => console.log("resolved:", comments),
    err => console.log("rejected:", err)
);

4、Promise.prototype.catch()

Promise.prototype.catch要領是.then(null, rejection)的別號,用於指定發作毛病時的回調函數。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 處置懲罰 getJSON 和 前一個回調函數運轉時發作的毛病
  console.log('發作毛病!', error);
});

上面代碼中,getJSON要領返回一個 Promise 對象,假如該對象狀況變成resolved,則會挪用then要領指定的回調函數;假如異步操縱拋出毛病,狀況就會變成rejected,就會挪用catch要領指定的回調函數,處置懲罰這個毛病。別的,then要領指定的回調函數,假如運轉中拋出毛病,也會被catch要領捕捉。

p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));

// 等同於
p.then((val) => console.log('fulfilled:', val))
  .then(null, (err) => console.log("rejected:", err));

下面是一個例子

const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

上面代碼中,promise拋出一個毛病,就被catch要領指定的回調函數捕捉。注重,上面的寫法與下面兩種寫法是等價的。

// 寫法一
const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 寫法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});

比較上面兩種寫法,能夠發明reject要領的作用,等同於拋出毛病。

假如 Promise 狀況已變成resolved,再拋出毛病是無效的。

const promise = new promise(function(resolve, reject) {
    resolve("ok");
});
promise
    .then((value) => console.log(value) )
    .catch((error) => console.log(error) );
// ok

上面代碼中,Promise 在resolve語句背面,再拋出毛病,不會被捕捉,即是沒有拋出。由於 Promise 的狀況一旦轉變,就永遠堅持該狀況,不會再變了。

Promise 對象的毛病具有“冒泡”性子,會一向向後通報,直到被捕捉為止。也就是說,毛病老是會被下一個catch語句捕捉。

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 處置懲罰前面三個Promise發生的毛病
});

上面代碼中,一共有三個 Promise 對象:一個由getJSON發生,兩個由then發生。它們當中任何一個拋出的毛病,都邑被末了一個catch捕捉。

平常來說,不要在then要領內里定義 Reject 狀況的回調函數(即then的第二個參數),老是運用catch要領。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,由於x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123

上面代碼中,someAsyncThing函數發生的 Promise 對象,內部有語法毛病。瀏覽器運轉到這一行,會打印出毛病提醒ReferenceError: x is not defined,然則不會退出歷程、停止劇本實行,2 秒以後照樣會輸出123。這就是說,Promise 內部的毛病不會影響到 Promise 外部的代碼,淺顯的說法就是“Promise 會吃掉毛病”。

這個劇本放在服務器實行,退出碼就是0(即示意實行勝利)。不過,Node 有一個unhandledRejection事宜,特地監聽未捕捉的reject毛病,上面的劇本會觸發這個事宜的監聽函數,能夠在監聽函數內里拋出毛病。

process.on('unhandledRejection', function (err, p) {
  throw err;
});

上面代碼中,unhandledRejection事宜的監聽函數有兩個參數,第一個是毛病對象,第二個是報錯的 Promise 實例,它能夠用來相識發作毛病的環境信息。

注重,Node 有計劃在將來取銷unhandledRejection事宜。假如 Promise 內部有未捕捉的毛病,會直接停止歷程,而且歷程的退出碼不為 0。

再看下面的例子。

const promise = new Promise(function (resolve, reject) {
  resolve('ok');
  setTimeout(function () { throw new Error('test') }, 0)
});
promise.then(function (value) { console.log(value) });
// ok
// Uncaught Error: test

上面代碼中,Promise 指定鄙人一輪“事宜輪迴”再拋出毛病。到了誰人時候,Promise 的運轉已完畢了,所以這個毛病是在 Promise 函數體外拋出的,會冒泡到最外層,成了未捕捉的毛病。

平常老是發起,Promise 對象背面要跟catch要領,如許能夠處置懲罰 Promise 內部發作的毛病。catch要領返回的照樣一個 Promise 對象,因而背面還能夠接着挪用then要領。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,由於x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// oh no [ReferenceError: x is not defined]
// carry on

上面代碼運轉完catch要領指定的回調函數,會接着運轉背面誰人then要領指定的回調函數。假如沒有報錯,則會跳過catch要領。

Promise.resolve()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// carry on

上面的代碼由於沒有報錯,跳過了catch要領,直接實行背面的then要領。此時,如果then要領內里報錯,就與前面的catch無關了。

catch要領當中,還能再拋出毛病。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,由於x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  return someOtherAsyncThing();
}).catch(function(error) {
  console.log('oh no', error);
  // 下面一行會報錯,由於 y 沒有聲明
  y + 2;
}).then(function() {
  console.log('carry on');
});
// oh no [ReferenceError: x is not defined]

上面代碼中,catch要領拋出一個毛病,由於背面沒有別的catch要領了,致使這個毛病不會被捕捉,也不會通報到外層。假如改寫一下,效果就不一樣了。

someAsyncThing().then(function() {
  return someOtherAsyncThing();
}).catch(function(error) {
  console.log('oh no', error);
  // 下面一行會報錯,由於y沒有聲明
  y + 2;
}).catch(function(error) {
  console.log('carry on', error);
});
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]

上面代碼中,第二個catch要領用來捕捉前一個catch要領拋出的毛病。

5、Promise.prototype.finally()

finally要領用於指定不論 Promise 對象末了狀況怎樣,都邑實行的操縱。該要領是 ES2018 引入規範的。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

上面代碼中,不論promise末了的狀況,在實行完then或catch指定的回調函數今後,都邑實行finally要領指定的回調函數。

下面是一個例子,服務器運用 Promise 處置懲罰要求,然後運用finally要領關掉服務器。

server.listen(port)
  .then(function () {
    // ...
  })
  .finally(server.stop);

finally要領的回調函數不接收任何參數,這意味着沒有辦法曉得,前面的 Promise 狀況究竟是fulfilled照樣rejected。這表明,finally要領內里的操縱,應當是與狀況無關的,不依賴於 Promise 的實行效果。

finally本質上是then要領的慣例。

promise
.finally(() => {
  // 語句
});

// 等同於
promise
.then(
  result => {
    // 語句
    return result;
  },
  error => {
    // 語句
    throw error;
  }
);

上面代碼中,假如不運用finally要領,一樣的語句須要為勝利和失利兩種狀況各寫一次。有了finally要領,則只須要寫一次。

它的完成也很簡樸。

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

上面代碼中,不論前面的 Promise 是fulfilled照樣rejected,都邑實行回調函數callback。

從上面的完成還能夠看到,finally要領老是會返回本來的值。

// resolve 的值是 undefined
Promise.resolve(2).then(() => {}, () => {})

// resolve 的值是 2
Promise.resolve(2).finally(() => {})

// reject 的值是 undefined
Promise.reject(3).then(() => {}, () => {})

// reject 的值是 3
Promise.reject(3).finally(() => {})

6、Promise.all()

Promise.all要領用於將多個 Promise 實例,包裝成一個新的 Promise 實例。

const p = Promise.all([p1, p2, p3]);

上面代碼中,Promise.all要領接收一個數組作為參數,p1、p2、p3都是 Promise 實例,假如不是,就會先挪用下面講到的Promise.resolve要領,將參數轉為 Promise 實例,再進一步處置懲罰。(Promise.all要領的參數能夠不是數組,但必需具有 Iterator 接口,且返回的每一個成員都是 Promise 實例。)

p的狀況由p1、p2、p3決議,分紅兩種狀況。

(1)只需p1、p2、p3的狀況都變成fulfilled,p的狀況才會變成fulfilled,此時p1、p2、p3的返回值構成一個數組,通報給p的回調函數。

(2)只需p1、p2、p3當中有一個被rejected,p的狀況就變成rejected,此時第一個被reject的實例的返回值,會通報給p的回調函數。

下面是一個詳細的例子。

// 天生一個Promise對象的數組
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

上面代碼中,promises是包括 6 個 Promise 實例的數組,只需這 6 個實例的狀況都變成fulfilled,或許个中有一個變成rejected,才會挪用Promise.all要領背面的回調函數。

下面是另一個例子。

const databasePromise = connectDatabase();

const booksPromise = databasePromise
  .then(findAllBooks);

const userPromise = databasePromise
  .then(getCurrentUser);

Promise.all([
  booksPromise,
  userPromise
])
.then(([books, user]) => pickTopRecommentations(books, user));

上面代碼中,booksPromise和userPromise是兩個異步操縱,只需比及它們的效果都返回了,才會觸發pickTopRecommentations這個回調函數。

注重,假如作為參數的 Promise 實例,本身定義了catch要領,那末它一旦被rejected,並不會觸發Promise.all()的catch要領。

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result);

const p2 = new Promise((resolve, reject) => {
  throw new Error('報錯了');
})
.then(result => result);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 報錯了

7、Promise.race()

Promise.race要領一樣是將多個 Promise 實例,包裝成一個新的 Promise 實例。

const p = Promise.race([p1, p2, p3]);

上面代碼中,只需p1、p2、p3當中有一個實例領先轉變狀況,p的狀況就隨着轉變。誰人領先轉變的 Promise 實例的返回值,就通報給p的回調函數。

Promise.race要領的參數與Promise.all要領一樣,假如不是 Promise 實例,就會先挪用下面講到的Promise.resolve要領,將參數轉為 Promise 實例,再進一步處置懲罰。

下面是一個例子,假如指定時候內沒有取得效果,就將 Promise 的狀況變成reject,不然變成resolve。

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

8、Promise.resolve()

偶然須要將現有對象轉為 Promise 對象,Promise.resolve要領就起到這個作用。

const jsPromise = Promise.resolve($.ajax('/whatever.json'));

上面代碼將 jQuery 天生的deferred對象,轉為一個新的 Promise 對象。

Promise.resolve等價於下面的寫法。


Promise.resolve('foo')
// 等價於
new Promise(resolve => resolve('foo'))

Promise.resolve要領的參數分紅四種狀況。
(1)參數是一個 Promise 實例

假如參數是 Promise 實例,那末Promise.resolve將不做任何修正、一成不變地返回這個實例。

(2)參數是一個thenable對象

thenable對象指的是具有then要領的對象,比方下面這個對象。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

Promise.resolve要領會將這個對象轉為 Promise 對象,然後就馬上實行thenable對象的then要領。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

上面代碼中,thenable對象的then要領實行后,對象p1的狀況就變成resolved,從而馬上實行末了誰人then要領指定的回調函數,輸出 42。

(3)參數不是具有then要領的對象,或基礎就不是對象

假如參數是一個原始值,或許是一個不具有then要領的對象,則Promise.resolve要領返回一個新的 Promise 對象,狀況為resolved。

const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

上面代碼天生一個新的 Promise 對象的實例p。由於字符串Hello不屬於異步操縱(推斷要領是字符串對象不具有 then 要領),返回 Promise 實例的狀況從一天生就是resolved,所以回調函數會馬上實行。Promise.resolve要領的參數,會同時傳給回調函數。

(4)不帶有任何參數

Promise.resolve要領許可挪用時不帶參數,直接返回一個resolved狀況的 Promise 對象。

所以,假如願望取得一個 Promise 對象,比較輕易的要領就是直接挪用Promise.resolve要領。

const p = Promise.resolve();

p.then(function () {
  // ...
});

上面代碼的變量p就是一個 Promise 對象。

須要注重的是,馬上resolve的 Promise 對象,是在本輪“事宜輪迴”(event loop)的完畢時,而不是鄙人一輪“事宜輪迴”的開始時。

setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');

// one
// two
// three

上面代碼中,setTimeout(fn, 0)鄙人一輪“事宜輪迴”開始時實行,Promise.resolve()在本輪“事宜輪迴”完畢時實行,console.log(‘one’)則是馬上實行,因而最早輸出。

9、Promise.reject()

Promise.reject(reason)要領也會返回一個新的 Promise 實例,該實例的狀況為rejected。

const p = Promise.reject('出錯了');
// 等同於
const p = new Promise((resolve, reject) => reject('出錯了'))

p.then(null, function (s) {
  console.log(s)
});
// 出錯了

上面代碼天生一個 Promise 對象的實例p,狀況為rejected,回調函數會馬上實行。

注重,Promise.reject()要領的參數,會一成不變地作為reject的來由,變成後續要領的參數。這一點與Promise.resolve要領不一致。


const thenable = {
  then(resolve, reject) {
    reject('出錯了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

上面代碼中,Promise.reject要領的參數是一個thenable對象,實行今後,背面catch要領的參數不是reject拋出的“出錯了”這個字符串,而是thenable對象。

    原文作者:豬豬豬惠婷
    原文地址: https://segmentfault.com/a/1190000014933858
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞