1.修改promise的狀態
let p = new Promise((resolve, reject) => {
//1. resolve 函數
// resolve('ok'); // pending => fulfilled (resolved)
//2. reject 函數
// reject("error");// pending => rejected
//3. 拋出錯誤
// throw '出問題了',rejected;
});
通過throw也可以修改promise狀態
2.能否執行多個回調
let p = new Promise((resolve, reject) => {
resolve('OK');
});
///指定回調 - 1
p.then(value => {
console.log(value);
});
//指定回調 - 2
p.then(value => {
alert(value);
});//都可以執行
3.改變狀態與指定回調的順序
1. 如果先指定的回調, 那當狀態發生改變時, 回調函數就會調用, 得到數據
// 常規: 先指定回調函數, 后改變的狀態
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1) // 后改變的狀態(同時指定數據), 異步執行回調函數
}, 1000);
}).then(// 先指定回調函數, 保存當前指定的回調函數
value => {},
reason => {console.log('reason', reason)}
)
2. 如果先改變的狀態, 那當指定回調時, 回調函數就會調用, 得到數據
// 如果先改狀態, 后指定回調函數
new Promise((resolve, reject) => {
resolve(1) // 先改變的狀態(同時指定數據)
}).then(// 后指定回調函數, 同步執行回調函數
value => {console.log('value2', value)},
reason => {console.log('reason2', reason)}
)
總結:只有當狀態改變才會執行回調
4.then方法返回promise結果由什么決定
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//執行 then 方法
let result = p.then(value => {
// console.log(value);
//1. 拋出錯誤
// throw '出了問題';
//2. 返回結果是非 Promise 類型的對象
// return 521;
//3. 返回結果是 Promise 對象
// return new Promise((resolve, reject) => {
// // resolve('success');
// reject('error');
// });
//不返回,promise的值是undefined
//返回的是pending狀態的promise,會中斷鏈式調用
}, reason => {
console.warn(reason);
});
console.log(result);
1.拋出錯誤,then返回的promise對象是rejected
2.promise內部返回結果是非promise對象,return number/string/boolean,then的返回的promise對象是resolve
3.then的promise返回結果是promise對象,由內部返回的promise對象來絕對then的promise對象的狀態
4.then內部不返回值,后面的then調用默認是undefined
5.promise如何串聯多個任務
1.promise的then返回一個promise對象,通過鏈式調用即可
2.通過then串聯同步/異步操作
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value);
}).then(value => {
console.log(value);
})
6.異常的穿透
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
// reject('Err');
}, 1000);
});
p.then(value => {
// console.log(111);
throw '失敗啦!';
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
異常的穿透,在改變狀態之后執行then中的回調,then的返回結果是promise,但是改變了promise的狀態,是rejected,返回的rejected的promise對象直接穿透到catch中
7.如何中斷promise鏈
有且只有一個方式返回一個pending狀態的promise
return new Promise(() => {})
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一個方式
return new Promise(() => {});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
8.錯誤的捕獲
首頁我們先要區分幾個概念:
第一,reject是用來拋出異常的,catch是用來處理異常的;
第二:reject是Promise的方法,而then和catch是Promise實例的方法(Promise.prototype.then 和 Promise.prototype.catch)。
1. 區別
主要區別就是,如果在then的第一個函數里拋出了異常,后面的catch能捕獲到,而then的第二個函數捕獲不到。
catch只是一個語法糖而己 還是通過then 來處理的,
大概如下所示字體:
Promise.prototype.catch = function(fn){
return this.then(null,fn);
}
then的第二個參數和catch捕獲錯誤信息的時候會就近原則,如果是promise內部報錯,reject拋出錯誤后,then的第二個參數和catch方法都存在的情況下,只有then的第二個參數能捕獲到,如果then的第二個參數不存在,則catch方法會捕獲到。
const promise = new Promise((resolve, rejected) => {
throw new Error('test');
});
//此時只有then的第二個參數可以捕獲到錯誤信息
promise.then(res => {
//
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});
//此時catch方法可以捕獲到錯誤信息
promise.then(res => {
//
}).catch(err1 => {
console.log(err1);
});
//此時只有then的第二個參數可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
throw new Error('hello');
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});
//此時只有then的第二個參數可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
throw new Error('hello');
}, err => {
console.log(err);
});
//此時catch可以捕獲到Promise內部拋出的錯誤信息
promise.then(res => {
throw new Error('hello');
}).catch(err1 => {
console.log(err1);
});
2. 兩個捕獲方法的比較
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
上面代碼中,第二種寫法要好於第一種寫法,理由是第二種寫法可以捕獲前面then方法執行中的錯誤,也更接近同步的寫法(try/catch)。因此,建議總是使用catch方法,而不使用then方法的第二個參數。