什麼是promise
promise是一個類,是現在比較常用的一個非同步解決方案,用來解決之前非同步程式設計的回撥地獄問題
常見的幾種非同步程式設計方法
- 回掉函式
- 事件監聽
- 釋出訂閱
- promise
- generator(一般不用)
- async、await(es8語法)
promise和回撥函式對比
promise版
let api = new Promise((resolve,reject)=>{
resolve("成功");
reject("失敗")
})
api
.then(val=>{
resolve(val)
})
.then(val=>{
resolve(val)
})
.then(val=>{
console.log(val) // 成功
})
使用回撥函式
$.get(url, data1 => {
console.log(data1)
$.get(data1.url, data2 => {
console.log(data1)
})
})
複製程式碼
這樣看起來是不是更加清晰了
promise的使用
- Promise 是一個建構函式, new Promise 返回一個 promise物件 接收一個excutor執行函式作為引數, excutor有兩個函式型別形參resolve reject
// excutor函式會立即執行,引數是resolve和reject函式
// 每個promise例項都有一個then方法
let promise = new Promise(function(resolve,reject){//excutor
resolve("成功");
reject("失敗")
})
//onfulfilled 成功, onrejectd 失敗
promise.then(function(val){ //onfulfilled
console.log(val) //成功
},function(err){ //onrejectd
console.log(err) //失敗
})
複製程式碼
promise有三個狀態
- pendding 等待狀態、resolved 成功態、rejected 失敗態
1.pendding 等待狀態 -> resolved 成功態
2.pendding 等待狀態 -> resolved 成功態
**注意:成功態和失敗態不能相互轉化,只能由 pending => fulfilled/rejected, 一旦修改就不能再變
promise物件方法**
手寫promise程式碼
function Promise(executor){
// promise 有三個狀態 pending fulfilled rejected
this.status = 'pending'; // 初始狀態
this.value = undefined; // 成功狀態時 返回的資訊
this.reason = undefined; // 失敗狀態時 返回的資訊
let self = this;
self.onResolveCallbacks = []; // 儲存成功狀態對應的onFulfilled函式
self.onRejectedCallbacks = []; // 儲存失敗狀態對應的onRejected函式
function reoslve(value){ // 變成成功態
if(self.status === 'pending'){
self.value = value;
self.status = 'fulfilled';
self.onResolveCallbacks.forEach(fn=>fn())
}
}
function reject(reason){ // 變成是失敗態
if(self.status === 'pending'){
self.reason = reason;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(fn=>fn())
}
}
try{
executor(reoslve,reject);
}catch(e){
reject(e);
}
}
// 這個方法要相容別人的promise 嚴謹一些 這個方法 要相容別人的promise
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){ // 防止返回的promise 和 then方法返回的promise 是同一個
return reject(new TypeError('迴圈引用'));
}
if(x!== null && (typeof x === 'object' || typeof x === 'function')){ // {}
let called;
try{
let then = x.then; // 看看這個物件有沒有then方法,如果有 說明x是promise {then:undefined}
if(typeof then === 'function'){
then.call(x,y=>{
if(called) return
called = true;
// 如果返回的是一個promise這個promise,resolve的結果可能還是一個promise,遞迴解析直到這個y是一個常量為止
resolvePromise(promise2,y,resolve,reject)
},r=>{
if(called) return // 防止呼叫失敗 又呼叫成功
called = true;
reject(r);
});
}else{
resolve(x); // {then:{}} {then:123}
}
}catch(e){ // 這個then方法 是通過 ObjectDefineProperty定義的
if(called) return
called = true; // 這個判斷為了防止出錯後 繼續要呼叫成功邏輯
reject(e);
}
}else{
resolve(x); // x就是普通常量
}
}
Promise.prototype.then = function(onfulfilled,onrejected){
// 引數的可選
onfulfilled = typeof onfulfilled ==='function'?onfulfilled :val=>val;
onrejected = typeof onrejected == 'function'?onrejected :err=>{throw err}
let self = this;
// 每個promise必須返回一個新的狀態 保證可以鏈式呼叫
let promise2 = new Promise(function(resolve,reject){
if(self.status === 'fulfilled'){
setTimeout(()=>{
try{
let x = onfulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
})
}
if(self.status === 'rejected'){
setTimeout(()=>{
try{
let x = onrejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
})
}
if(self.status === 'pending'){
self.onResolveCallbacks.push(function(){
setTimeout(()=>{
try{
let x = onfulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
})
});
self.onRejectedCallbacks.push(function(){
setTimeout(()=>{
try{
let x = onrejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
})
})
}
});
return promise2
}
// npm install promises-aplus-tests -g
// promises-aplus-tests promise.js
Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise
複製程式碼