說明
Node.js中,以異步(Async)回調著稱,使用了異步,提高了程序的執行效率,但是,代碼可讀性較差的。
假如有幾個異步操作,后一個操作需要前一個操作的執行完畢之后返回的數據才能執行下去,如果使用Node.js,就需要一層層嵌套下去,Promised對象就是針對此問題所提出來的的解決辦法。
基本概念
Promise對象狀態:
pending
初始狀態,也稱為未定狀態,就是初始化Promise時,調用executor執行器函數后的狀態。fulfilled
完成狀態,意味着異步操作成功。rejected
失敗狀態,意味着異步操作失敗。
狀態轉換只有這兩種pending->fulfilled pending->rejected,可返回的這個Promise對象的狀態主要是根據promise1.then()方法返回的值:
狀態轉化是單向的,不可逆轉,已經確定的狀態(fulfilled/rejected)無法轉回初始狀態(pending)
當狀態為rejected,該promise無法繼續往下執行,需要添加一個catch獲得異常信息
回調函數:
resolve
當pending
狀態轉為fulfilled
狀態時候回調(操作成功)reject
當pending
狀態轉為rejected
狀態時候回調(操作失敗)
方法:
- then()
- catch()
- all()
- race()
基本使用
new Promise(function(resolve,reject){
//這里面實現異步操作,ajax等..
//獲得結果,回調傳參
if(/*success*/){
resolve();
}else{
reject();
}
});
//雖然沒有去執行setTimeOut函數,但是Promise會自動執行,所以,一般需要將Promise寫在一個function里面
new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.random();
//當隨機數小於0.5,當前promise完成了執行
if(num<0.5){
resolve(num);
}else{
reject("錯誤,num>=0.5");
}
console.log('執行完成');
},2000);
});
let p =new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.random();
//當隨機數小於0.5,當前promise完成了執行
if(num<0.5){
resolve(num);
}else{
reject(num);
}
console.log('執行完成');
},2000);
});
p.then(function(data){
//這里的data是之前resolve中的回調參數
console.log(data);
},function(error){
//這里的error是之前resolve中的回調參數
console.log("錯誤原因為"+error);
});
進階使用
then()
Promise then(fun(resolve,reject))
p.then(function(data){
//這里的data是之前resolve中的回調參數
console.log(data);
},function(data){
//這里的data是之前resolve中的回調參數
console.log("錯誤");
console.log(data);
});
then方法,可以接收回調的參數並進行處理,then方法返回的是一個Promise對象。這里,我們主要關心的是返回的Promise對象的狀態。
可返回的這個Promise對象的狀態主要是根據promise1.then()方法返回的值:
- 如果then()方法中返回了一個參數值,那么返回的Promise將會變成接收狀態。
- 如果then()方法中拋出了一個異常,那么返回的Promise將會變成拒絕狀態。
- 如果then()方法調用resolve()方法,那么返回的Promise將會變成接收狀態。
- 如果then()方法調用reject()方法,那么返回的Promise將會變成拒絕狀態。
- 如果then()方法返回了一個未知狀態(pending)的Promise新實例,那么返回的新Promise就是未知狀態。
- 如果then()方法沒有明確指定的resolve(data)/reject(data)/return data時,那么返回的新Promise就是接收狀態,可以一層一層地往下傳遞。
let p =new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.random();
//當隨機數小於0.5,當前promise完成了執行
if(num<0.5){
resolve(num);
}else{
reject(num);
}
console.log('執行完成');
},2000);
});
p.then(function(data){
//用上次獲得的數據執行相關的異步操作
},function(error){
//出現錯誤,處理錯誤信息
});
let p =new Promise(function(resolve,reject){
setTimeout(function(){
resolve("hello");
console.log('執行完成');
},2000);
});
p.then(function(data){
console.log(data);
}).then(function(){
setTimeout(function(){
console.log("過了5s,繼續執行");
},5000);
});
let p =new Promise(function(resolve,reject){
setTimeout(function(){
resolve("hello");
console.log('執行完成');
},2000);
});
p.then(function(data){
console.log(data);
//處理完數據之后,返回新的數據,給下次異步操作處理
return "this is new data"
}).then(function(data){
setTimeout(function(){
console.log("過了5s,繼續執行");
console.log(data);
},5000);
});
catch()
catch()方法和then()方法一樣,都會返回一個新的Promise對象,它主要用於捕獲異步操作時出現的異常。
因此,我們通常省略then()方法的第二個參數,把錯誤處理控制權轉交給其后面的catch()函數。
下面的兩段代碼塊,實現的功能是一樣的。
let p =new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.random();
//當隨機數小於0.5,當前promise完成了執行
if(num<0.5){
resolve(num);
}else{
reject(num);
}
console.log('執行完成');
},2000);
});
p.then(function(data){
//用上次獲得的數據執行相關的異步操作
},function(error){
//出現錯誤,處理錯誤信息
});
let p =new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.random();
if(num<0.5){
resolve(num);
}else{
reject(num);
}
console.log('執行完成');
},2000);
});
p.then(function(data){
//用上次獲得的數據執行相關的異步操作
}).catch(function(error){
//處理錯誤信息
});
race()
傳入參數為可迭代的對象,如數組
兩個異步任務同時向同一個url發送請求,誰先得到數據,另外的那個異步任務獲得的數據就會被丟棄
//2s后輸出“執行完成1”
let p =new Promise(function(resolve){
setTimeout(function(){
resolve("hello");
console.log('執行完成1');
},2000);
});
//1s后輸出“執行完成2”
let p1 =new Promise(function(resolve){
setTimeout(function(){
resolve("hello 2");
console.log('執行完成2');
},1000);
});
//兩個異步任務同時開始
let mixedPromisesArray = [p,p1];
let p3 = Promise.race(mixedPromisesArray).then(data=>{
//這里的data為hello 2,hello被丟棄
console.log(data);
});
all()
參數也是可迭代的對象,如數組
一般用於幾個任務同時並行運行的情況
當某個任務失敗,狀態就會變為reject
//2s后輸出“執行完成1”
let p =new Promise(function(resolve){
setTimeout(function(){
resolve("hello");
console.log('執行完成1');
},2000);
});
//1s后輸出“執行完成2”
let p1 =new Promise(function(resolve){
setTimeout(function(){
resolve("hello 2");
console.log('執行完成2');
},1000);
});
//兩個異步任務同時開始
let mixedPromisesArray = [p,p1];
let p3 = Promise.all(mixedPromisesArray).then(data=>{
//這里的data數組,存放着之前兩個異步回調傳的數據
console.log(data);
});