什么是promise
ES6異步編程的一種解決方案,將異步操作以同步的方式表達出來,避免層層嵌套的回調函數
為什么要用promise
- 指定回調函數的方式更加靈活
- 使用純回調函數方式,必須在異步任務執行前指定回調函數
// 成功的回調函數
function successCallback(result) {
console.log("音頻文件創建成功: " + result);
}
// 失敗的回調函數
function failureCallback(error) {
console.log("音頻文件創建失敗: " + error);
}
createAudioFileAsync(audioSettings, successCallback, failureCallback)
- promise 可以在啟動異步任務后指定回調函數,甚至可以在異步任務結束后綁定回調函數
const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);
setTimeout(() => {
promise.then(successCallback, failureCallback);
},2000)
- 支持鏈式調用,解決回調地獄
回調地獄:回調函數嵌套調用,外部回調函數異步執行的結果,是嵌套的回調函數執行的條件
嵌套的回調函數不便于閱讀、不便于異常處理
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
Promise 鏈式調用
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
promise鏈式調用異常傳遞
new Promise((resolve,reject) => {
reject(1)
}).then(
value => {
console.log('onResolved',value)
return 2
},
// error => { throw error }
// error => Promise.reject(error)
).then(
value => {
console.log('onResolved',value)
return 3
},
// error => { throw error }
).catch(reason => {
console.log('onRejected',reason)
})
輸出:onReject 1
一遇到異常拋出,瀏覽器就會順著 Promise 鏈尋找下一個 onRejected 失敗回調函數或者由 .catch() 指定的回調函數,相當于注釋代碼的兩種寫法之一
中斷promise鏈
new Promise((resolve, reject) => {
reject(1);
})
.then(() => {
console.log(2);
})
.catch(() => {
console.log(3);
//要中斷catch()后面的then()方法,
return new Promise(() => {}); //返回一個padding的promise
})
.then(() => {
console.log(3);
});
promise的特點
對象的狀態不受外界影響。Promise對象代表一個異步操作,有三種狀態:pending(進行中)、resolved(已成功)和rejected(已失敗)
一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從pending變為resolved和從pending變為rejected
promise內部發生錯誤,不會影響到外部程序的執行。
無法取消Promise。一旦新建它就會立即執行,無法中途取消。其次,如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。第三,當處于pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)
用法
創造promise 實例時,必須傳入一個函數作為參數
new promise(() => {});
該函數可以接收另外兩個由JavaScript引擎提供的函數,resolve和reject。函數作用:
- resolve——將Promise對象的狀態從pending變為resolved,將異步操作的結果,作為參數傳遞出去
- reject——將Promise對象的狀態從pending變為rejected,將異步操作報出的錯誤,作為參數傳遞出去
let promise = new promise((resolve, reject) => {
//do something
if(true){
//將參數返回,供then方法使用
resolve('value');
}else {
reject('error');
}
});
promise 實例方法
promise.prototype.then()
Promise實例生成以后,可以用then方法分別指定resolved狀態和rejected狀態的回調函數。
then方法返回的是一個新的Promise實例
promise.then(
//resolved時調用,value為resolve函數返回的參數
value => {
console.log(value);
},
err => {
//reject時調用
console.log(err);
}
);
當then方法只有一個函數參數時,此時為resolved狀態的回調方法
promise .then(value => {
console.log(value);
})
.catch(err => {
//
}
`推薦這種方式,可以捕獲前面then方法執行中的錯誤
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的別名
Promise 新建后就會立即執行,并且調用resolve或reject后不會終結 Promise的參數函數的執行。
let promise = new Promise(function(resolve){
console.log('promise');
resolve();
console.log(1)
})
promise.then(function() {
console.log('resolved');
})
console.log(2)
//promise
//1
//2
//resolved
Promise.then()返回的promise狀態是什么?
由then()指定的回調函數的執行結果決定
1、如果拋出異常,返回的promise變為rejected,error為拋出的異常
2、如果返回非promise的任意值,返回的promise變為resolved狀態,value為返回的值
3、如果返回另一個新的promise,此promise的結果就是返回的promise的結果
const p = new Promise(function(resolve,rejected){
resolve(1)
})
p.then(value => {
//情況1:拋出異常
throw '錯誤'
//2.返回一個值
return value+1;
//3.返回一個Promise
return new Promise((resolve, reject) => {
resolve(value+2)
});
return new Promise((resolve, reject) => {
reject(value+3)
});
//4.沒有返回值
相當于 return undefined
}).then(value => {
console.log('onResolved',value);
},error => {
console.log('onRejected',error)
});
- 拋出的異常將作為then方法返回的promise的reject的值傳遞出
輸出: onRejected 錯誤
- return的值將作為then方法返回的promise的resolve的值傳遞出
輸出: onResolved 2
- return 的promise的結果將作為then方法返回的promise的結果
分別輸出: onResolved 3 ,onRejected 4
- 構造then方法的函數沒有向then方法返回的promise對象的resolve方法傳遞值。因此resolve返回的是undefined
輸出: onResolved undefined
- promise.catch()
- promise.finally() 無論成功失敗都執行
靜態api方法
promise.all() 將多個 Promise 實例,包裝成一個新的 Promise 實例
const p =Promise.all([p1, p2, p3]);
p1,p2,p3都是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.race()方法是將多個Promise實例包裝為一個實例
const p = Promise.race([p1, p2, p3]);
上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。
Promise.resolve()
Promise.resolve(1)
// 等價于
new Promise(resolve => resolve(1))
Promise.resolve()方法的參數:
- 參數是promise實例
返回這個實例 - 參數是一個thenable對象
thenable對象指的是具有then方法的對象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value); // 42
});
Promise.resolve()方法會將這個對象轉為 Promise 對象,然后就立即執行thenable對象的then()方法。
- 參數不是具有then()方法的對象,或根本就不是對象
如果參數是一個原始值,或者是一個不具有then()方法的對象,則Promise.resolve()方法返回一個新的 Promise 對象,狀態為resolved。
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
//hello
- 不帶任何參數
直接返回一個resolved狀態的 Promise 對象。