1、Promise是什麼?
- promsie是ES6新增的一個特性,它已經列入ES6的正式規範中
- promise是抽象處理物件以及對其進行各種操作的元件,是一種非同步流程的控制手段。
- javaScript和Node都是單執行緒非阻塞的,所以就會有非同步回撥的問題,promise就是為了解決這類問題的。
- Promise可以支援多個併發的請求,獲取併發請求中的資料。
- Promise可以使用鏈式呼叫的方法來組織程式碼,所以使用Promise物件後,就可以將非同步操作以同步操作的流程表達出來,避免了層層巢狀讓程式碼更加的直觀。
示例:
$.ajax(url1, function(data1){
// do something...
$.ajax(url2, function(data2){
// do something...
$.ajax(url3, function(data3){
// do something...
done(data3); // 返回資料
});
});
});
複製程式碼
未使用promise,回撥必須層層巢狀(回撥地獄),程式碼難以維護,第一的輸出是第二個的輸入時,需要等待上一個操作完成才可以進行下一個操作,造成不必要的等待。
2、Promise的狀態
2.1 Promise物件有三種狀態
- Pending(等待態)
- 既不是resolve也不是reject的狀態,也就是promise物件剛建立後的初始化狀態;
- Resolved/Fulfilled(成功態)
- resolve(成功)時,此時會呼叫onFuifilled;
- Rejected(失敗態)
- reject(失敗)時,此時會呼叫onRejected;
promise只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
2.2 狀態一旦改變就不會再變,任何時候都可以得到這個結果。
- 如果一旦promise成功了就不能失敗,相反也是一樣的,只有狀態是等待的狀態時才可以轉化狀態
- promise物件的狀態改變,只有兩種可能:從Pending變為Resolved和從Pending變為Rejected
pending->fulfilledpending->rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果.
2.3 Promise的缺點
- 無法取消,一旦新建就會立即執行,無法中途取消。
- 如果不設定回撥函式,promise內部丟擲的錯誤,不會反應到外部。
- 當處於pending狀態時,無法確定進展到哪一階段,剛開始還是即將完成。
3、Promise的使用
3.1基本用法
- 首先要new一個Promise,將Promise例項化
- 例項化的promise可以傳兩個引數,一個是成功之後的resolve,一個是失敗之後的reject
- Promise本省只有一個引數,叫executor(執行器),預設new時就會呼叫
- 每一個Promise的例項上都有一個then方法(非同步的),可以用then方法分別指定Resolved狀態和Reject狀態的回撥函式
程式碼示例: 預設promise中的executor預設執行
let p=new Promise((resolve,reject)=>{
console.log(1);
});
console.log(2);
複製程式碼
程式碼示例: 呼叫onFuifilled
let p=new Promise((resolve,reject)=>{
resolve('成功');
});
p.then((value)=>{//value成功的原因
console.log(value);
},(err)=>{//err失敗的原因
console.log(err);
})
複製程式碼
程式碼示例: 呼叫onRejected
let p=new Promise((resolve,reject)=>{
reject('失敗');
});
p.then((value)=>{//value成功的原因
console.log(value);
},(err)=>{//err失敗的原因
console.log(err);
})
複製程式碼
程式碼示例: 成功了就不能失敗,相反也一樣
let p=new Promise((resolve,reject)=>{//
resolve('成功');
reject('失敗');
});
p.then((value)=>{//value成功的原因
console.log(value);
},(err)=>{//err失敗的原因
console.log(err);
})
複製程式碼
程式碼示例: 成功了就不能失敗,相反也一樣
let p=new Promise((resolve,reject)=>{
throw new Error('發生錯誤');
});
p.then((value)=>{//value成功的原因
console.log(value);
},(err)=>{//err失敗的原因
console.log(err);
})
複製程式碼
3.2鏈式操作
- 通過維護狀態、傳遞狀態的方式來使回撥能夠及時的呼叫,上一個操作完成之後才可以進行下一個操作,相比callback更靈活簡單
- promise實現鏈式呼叫返回的並不是this,而是一個新的promise
程式碼示例:
Promise1().then((value)=>{
console.log(valuse);
return Promise2();
}).then((value)=>{
console.log(value);
return Promise3();
}).then((value)=>{
console.log(value);
})//可以then到天荒地老
function Promise1(){
return new Promsie((resolve,reject)=>{
setTimeout(function(){//非同步操作
console.log('非同步1');
resolve('非同步1傳的值');
},1000);
})
}
function Promise2(){
return new Promsie((resolve,reject)=>{
setTimeout(function(){//非同步操作
console.log('非同步2');
resolve('非同步2傳的值');
},3000);
})
}
function Promise3(){
return new Promsie((resolve,reject)=>{
setTimeout(function(){//非同步操作
console.log('非同步3');
resolve('非同步3傳的值');
},2000);
})
}
複製程式碼
輸出的值為: 非同步1 非同步1傳的值 非同步2 非同步2傳的值 非同步3 非同步3傳的值
3.2 Promise的catch方法
- catch方法是then(onFulfilled,onRejected)方法中onRejected函式的簡單寫法,也就是可以寫成then(fn).catch(fn),相當於then(fn).then(null,fn);
程式碼示例:
let p=((isReady)=>{
return new Promise(()=>{
if(isready){
return resolve('hello');
}else{
return reject('failure');
}
});
})
p(true).then((value)=>{
console.log('resolved');
console.log(value);
console.log(aa);
}).catch((err)=>{
console.log('rejected');
console.log(err);
});
複製程式碼
輸出的值為: resolved hell rejected ReferenceError: aa is not defined...
3.3 promise.all方法
- promise.all接收一個為promise物件的陣列作為引數,當這個陣列裡所有的promise物件都變為resolve時,該方法才會返回。
程式碼示例:
let p1=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('Promise1');
},1000);
})
let p2=new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('Promise2');
},3000);
})
Promise.all([p1,p2]).then((result)=>{
console.log(result);
})
複製程式碼
輸出結果 ['Promise1','Promise2']
3.4 promise.race方法
- race的意思賽跑,也就是看誰跑的快,跑的快的就贏了。因此,promise.race也是傳入一個陣列,但是與promise.all不同的是,promise.race只返回跑的快的值。
程式碼例項:
let p1=new Promise((resolve,reject)=>{
setTimeout(function(){
console.log(1);
resolve('Promise');
},3000);
})
let p2=new Promise((resolve,reject)=>{
console.log(2);
resolve('Promise2');
},1000)
Promise.race([p1,p2]).then((result)=>{
console.log(result);
})
複製程式碼
輸出結果: 2 Promised 1
- 可以看到傳的值中,只有p2的返回了,但p1沒有停止,依然執行。
Promise的基礎就到這裡了,如果您覺得文章有用請點贊!!!