Promise : Promise 是一個非同步操作返回的物件,用來傳遞非同步操作的訊息。
Promise 的三種狀態:
- Pending Promise物件例項建立時候的初始狀態
- Fulfilled 可以理解為成功的狀態
- Rejected 可以理解為失敗的狀態
使用 Promise :
let promise = new Promise((resolve, reject) => {
/* 非同步操作 呼叫 resolve / reject */
});
promise.then(Fulfilled,Rejected)
複製程式碼
根據自己對 Promise 的理解,實現一個Promise :
/* 定義初始態 */
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
function Promise(executor) {
let self = this;
self.status = PENDING;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
/* 如果 promise的狀態為 pendding,轉為成功態 */
function resolve(value) {
if(value != null && value.then && typeof value.then == 'function'){
return value.then(resolve, reject);
}
setTimeout(function () {
if(self.status == PENDING){
self.status = FULFILLED;
self.value = value;
self.onResolvedCallbacks.forEach(cb=>cb(self.value))
}
})
}
/* 如果 promise的狀態為 pendding,轉為失敗態 */
function reject(reason) {
setTimeout(function () {
if(self.status == PENDING){
self.status = REJECTED;
self.value = reason;
self.onRejectedCallbacks.forEach(cb=>cb(self.value))
}
})
}
try{
executor(resolve,reject);
}catch(e){
reject(e)
}
}複製程式碼
實現 Promise then 方法,解決多層巢狀問題 :
/* 解決多層巢狀 */
function resolvePromise(promise2,x,resolve,reject) {
if(promise2 === x){
return reject(new TypeError('迴圈引用~'));
}
let called =false;
if(x instanceof Promise){
if(x.status == PENDING){
x.then(function (y) {
resolvePromise(promise2, y, resolve, reject);
}, reject)
}else{
x.then(resolve, reject);
}
}else if(x != null && ((typeof x =='object') || (typeof x == 'function'))){
try {
let then = x.then;
if (typeof then == 'function') {
then.call(x, function (y) {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, function (err) {
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x);
}
}catch(e){
if(called) return;
called = true;
reject(e)
}
}else {
resolve(resolve(x));
}
}
Promise.prototype.then = function (onFulfilled,onRejected) {
onFulfilled = typeof onFulfilled == 'function'? onFulfilled: function(value){return value};
onRejected = typeof onRejected == 'function'? onRejected: reason=>{throw reason};
let self = this;
let promise2;
switch (self.status) {
case FULFILLED:
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = (onFulfilled(self.value));
resolvePromise(promise2, x, resolve, reject);
} catch(e) {
reject(e);
}
})
});
break;
case REJECTED:
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try{
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
}catch(e){
reject(e)
}
})
})
break;
case PENDING:
promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallbacks.push(function () {
try{
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
}catch(e){
reject(e);
}
})
self.onRejectedCallbacks.push(function () {
try{
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
}catch(e){
reject(e);
}
})
})
break;
default:
throw 'promise 狀態錯誤';
}
return promise2;
}複製程式碼
Promise.catch 的實現 :
/* catch 只傳失敗的回撥 */
Promise.prototype.catch = function(onRejected){
this.then(null,onRejected);
}複製程式碼
Promise 的幾種常見方法:
Promise.all :
引數 : 接受一個陣列,陣列內是 Promise 例項;
返回值:返回一個 Promise 例項,這個 Promise 例項的狀態取決於引數的 Promise 例項的狀態變化。
Promise.race :
引數 : 接受一個陣列,陣列內是 Promise 例項;
返回值:返回一個 Promise 例項,這個 Promise 例項的狀態取決於引數的 Promise 例項的狀態變化。
Promise.resolve :
返回值:返回一個 Promise 例項,這個 Promise 例項處於 resolve 狀態。
Promise.reject :
返回值:返回一個 Promise 例項,這個 Promise 例項處於 reject 狀態。
相關程式碼 :
function gen(times,cb){
let result = [],count=0;
return function(i,data){
result[i] = data;
if(++count==times){
cb(result);
}
}
}
Promise.all = function(promises){
return new Promise(function(resolve,reject){
let done = gen(promises.length,resolve);
for(let i=0;i<promises.length;i++){
promises[i].then(function(data){
done(i,data);
},reject);
}
});
}
Promise.race = function(promises){
return new Promise(function(resolve,reject){
for(let i=0;i<promises.length;i++){
promises[i].then(resolve,reject);
}
});
}
/* 返回一個直接成功的promise */
Promise.resolve = function(value){
return new Promise(function(resolve){
resolve(value);
});
}
/* 返回一個直接失敗的promise */
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
});
}複製程式碼
PS : 以上只是自己的一些淺顯的理解,如有問題,還請指正。^_^