即使不是reject的錯誤,在錯誤函數中一樣能夠獲得
```
var p = new Promise((resolve, reject) => {foo.bar(); resolve(1);})
p.then(data => console.log(data), err => console.log('ooh...', err)); //ohh... foo is not defined
```
如果是resolve函數中的錯誤,那么錯誤就無法走到reject函數中
```
var p = new Promise((resolve, reject) => resolve(1));
p.then(data => foo.bar(), err => console.log(err)); //直接拋錯
```
```
var p = new Promise((resolve, reject) => resolve(1));
p.then(data => foo.bar(), err => console.log(err))
.catch(err => console.log('ooh...', err)); //ooh.. foo is not defined
```
如果resolve一個promise,那么兩個promise會進行異步展開并返回一個promise(如果完成或拒絕函數返回一個Promise,它將會被展開,不管它的決議是什么,都會成為當前then返回的鏈接Promise的決議值)
```
var p1 = new Promise((resolve, reject) => resolve(42));
var p2 = new Promise((resolve, reject) => resolve(p1));
var p3 = new Promise((resolve, reject) => resolve(p2));
p3.then(data => console.log(data)); //42
```
下面兩個的行為是一樣的,我們更喜歡用第一種
```
var p1 = new Promise((resolve, reject) => resolve(42));
var p2 = Promise.resolve(42);
```
而如果向Promise.resolve傳遞一個真正的promise,則只會返回一個promise
```
var p1 = Promise.resolve(42);
var p2 = Promise.resolve(p1);
p1 === p2; //true
```
#### 鏈式流
每次調用.then都會返回一個新的Promise,不管回調函數返回的值是什么,該值都會被包成新的promise供下一個鏈式使用(沒有返回值則是undefined)
```
var p = Promise.resolve(21);
p.then(v1 => {console.log(v1); return v1 * 2})
.then(v2 => console.log(v2))
.then(v3 => console.log(v3));
// 21
// 42
//undefined
```
直接return并不直觀,因此建議用:
```
var p = new Promise.resolve(21);
p.then(v1 => {console.log(v1); return new Promise(resolve => resolve(v1 * 2))})
.then(v2 => console.log(v2))
.then(v3 => console.log(v3));
```
這就是promise的強大之處,每一步都必須等待前一步結束:
```
var p = Promise.resolve(21);
p.then(v => {console.log(v); return new Promise(resolve => setTimeout(() => resolve(v * 2), 100))})
.then(nv => console.log(nv));
//21
//100ms后 42
```
.then的完成函數或拒絕函數中發生的異常都會在下一個then的異常函數中捕獲
出現異常,在拒絕函數中處理后promise會繼續執行下去。如果誰都沒有處理這個異常,那么就會走到catch中并且中斷整個Promise
前面提到的,resolve中傳入一個Promise則會對兩個Promise進行展開,如果reject中傳入一個Promise則不會展開,.then的拒絕函數中接收的是這個reject的傳入的Promise
```
var p = Promise.reject('oops');
var p1 = new Promise((resolve, reject) => resolve(p));
p1.then(v => console.log(v), err => console.log('ooh...', err)); //ooh... oops
var p = Promise.resolve(21);
var p1 = new Promise((resolve, reject) => reject(p));
p1.then(v => console.log('not error'), err => console.log(err)); //Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
```
#### 錯誤處理
try catch只能處理同步錯誤
```
try {
setTimeout(() => baz.bar(), 100);
//100ms后拋出全局錯誤
}
catch(err) {console.log('oops'); /*永遠不會走到catch中*/
}
```
#### API
all
只有所有的promise都完成了all才會完成,有一個出錯整體就reject
記住要為每一個promise做錯誤處理而不僅僅是給all
```
var p1 = Promise.resolve(21);
var p2 = Promise.resolve(22);
Promise.all([p1, p2]).then(data => console.log(data)); //[21, 22]數組
```
race
同樣接收promise數組返回promise,但是promise們是處于競爭狀態的,有一個先resolve則整體就resolve了,整體resolve的值就是該promise resolve的值(先到的先勝利)。有任何一個reject了則整體reject。
promise無論是.then還是.catch都是返回promise
```
function foo(x ,y) {
return new Promise(resolve => resolve(x + y)).then(v => v * 2);
}
foo(2, 3).then(v => console.log(v)); //10
//因為new Promise(...).then(...)返回這個Promise,所以foo(2, 3)可以繼續使用這個promise,由于return v * 2會包裝成Promise傳入到下一個then中,所以最后的v是10
```
- 你不知道的JS上
- 第一部分 第三章 函數作用域和塊作用域
- 第一部分 第四章 提升
- 第一部分 第五章 閉包
- 第二部分 第一章 關于this
- 第二部分 第二章 this全面解析
- 第二部分 第三章 對象
- 第二部分 第五章 原型
- 第二部分 第六章 行為委托
- 你不知道的JS中
- 第一部分 第二章 值
- 第一部分 第三章 原生函數
- 第一部分 第四章 強制類型轉換
- 第一部分 第五章 語法
- 第二部分 第一章 異步
- 第二部分 第三章 Promise
- 第二部分 第四章 生成器
- 第二部分 第五章 性能
- 你不知道的JS下
- 第一部分 總結
- 第二部分 第二章 語法
- 第二部分 第三章 代碼組織
- 第二部分 第四章 Promise
- 第二部分 第五章 集合
- 第二部分 第六章 新增API
- 第二部分 第七章 元編程
- 第二部分 第八章 ES6之后