用原生js手寫實現promise,看了網上很多實現,最終寫出自己的簡易版promise,記錄一下
前言:使用及呼叫同原生Promise方法,只實現了then(resolve),catch(reject),finally()三個方法,不涉及Promise.race(),Promise.all();
-
建構函式:
let that; // 儲存 mPromise
/**
* 因為每次 new mPromise(then, catch的時候都需要鏈式呼叫)會呼叫 mPromise(constructor),
* 所以放到外面
*/
// 狀態、引數配置
let config = {
status: null,
resolveParam: null,
rejectParam: null
};
/**
* mPromise函式:原生Promise的手動實現
* @param {new mPromise時傳入的回撥函式} callback
*/
function mPromise(callback) {
that = this;
// 往new mPromise時傳入的回撥函式,傳回兩個引數
callback(that.resolve, that.reject);
}
複製程式碼
-
原型:
mPromise.prototype = {
constructor: mPromise,
resolve(param) {
config.rejectParam = null; // 重置 reject 引數
config.resolveParam = param;
config.status = 'PENDING';
},
reject(param) {
config.resolveParam = null; // 重置 resolve 引數
config.rejectParam = param;
config.status = 'PENDING';
},
then(_fn) {
// 有resolve才呼叫
if (config.resolveParam !== null) {
config.status = 'RESOLVED';
// 執行 then 的回撥,捕獲其中的報錯,呼叫 catch
try {
_fn(config.resolveParam);
} catch (err) {
config.rejectParam = err;
that.catch(() => {});
}
}
return new mPromise(() => {});
},
catch(_fn) {
// 有reject才呼叫
if (config.rejectParam !== null) {
config.status = 'REJECTED';
_fn(config.rejectParam);
}
return new mPromise(() => {});
},
finally(_fn) {
// 初始化配置
config = {
status: null,
resolveParam: null,
rejectParam: null
};
_fn();
}
};
複製程式碼
-
使用方式同原生Promise:
let f1 = function(num) {
return new mPromise((resolve, reject) => {
if (num < 10) resolve(num);
else if (num === 11) reject(num);
});
};
複製程式碼
-
然後呼叫:
f1(6)
.then(res => {
// cc; 開啟的話,會被 try catch捕獲,觸發catch,而不會往下走
console.log('then: ', res); // then 6
})
.catch(err => {
// 這裡會捕獲 then 裡面的報錯
console.log('catch: ', err); // ReferenceError: cc is not defined
});
f1(11)
.then(res => {
console.log('then: ', res);
})
.catch(err => {
console.log('catch: ', err); // catch 11
})
.finally(() => {
console.log('11 finally\n'); // 11 finally
});
f1(12)
.then(res => {
console.log('then: ', res);
})
.catch(err => {
console.log('catch: ', err);
})
.finally(() => {
console.log('12 finally\n'); // 12 finally
});
複製程式碼
結果:
then裡面不報錯:
then裡面有報錯:
到此,結束!