Git源码:
https://github.com/slhuang520/study/tree/master/web/es6/test/src/promise
整体结构图如下:
MyPromise .js
// require("babel-register"); //自动编译
// import "core-js"; //引入 polyfill
// import "regenerator-runtime/runtime";
const STATUS_PENDING = "pending";
const STATUS_RESOLVED = "resolved";
const STATUS_REJECTED = "rejected";
class MyPromise {
constructor(fn) {
this.catchAble = false;
this.isRejected = false;
this.state = STATUS_PENDING;
this.handlers = [];
this.frontVal;
setTimeout(() => {
fn(this.resolve.bind(this), this.reject.bind(this));
});
}
then(resolve, reject) {
this.handlers.push({resolve,reject});
return this;
}
resolve(value){
if (value && typeof value.then === "function") { //是否返回的是一个 Promise 对象
value.handlers.push(...this.handlers.splice(0));
return;
}
this.frontVal = value;
if (this.state === STATUS_PENDING) {
this.state = STATUS_RESOLVED;
}
this.deal();
}
reject(value) {
if (value && typeof value.then === "function") {
value.handlers.push(...this.handlers.splice(0));
return;
}
this.frontVal = value;
this.state = STATUS_REJECTED;
this.deal();
}
catch(fun) {
this.handlers.push({
resolve: undefined,
reject: fun
});
this.catchAble = true;
}
deal() {
let funObj = this.findFn(),
fn;
if (!funObj) {
return;
}
if (this.state === STATUS_RESOLVED) {
fn = funObj.resolve;
} else if (this.state === STATUS_REJECTED) {
fn = funObj.reject;
}
if ((!fn || typeof fn !== "function") && this.state === STATUS_REJECTED) {
if (this.catchAble) {
this.isRejected = true;
return this.deal();
}
throw new Error("Exist Un-catched Error!");
}
this.state = STATUS_RESOLVED;
if (typeof fn === "function"){
this.resolve(fn(this.frontVal)); //为何这里直接调用resolve?而不区分reject?是因为reject处理之后,后续的then还需要继续执行
} else {
this.resolve(fn || this.frontVal);
}
}
findFn() {
if (!this.handlers.length) {
return;
}
let funObj = this.handlers.shift();
if (this.isRejected) {
if (typeof funObj.resolve !== "undefined") {
return this.findFn();
}
this.isRejected = false;
}
return funObj;
}
}
export default MyPromise;
TestMyPromise.js
import Promise from "./MyPromise.js";
class TestMyPromise {
constructor() {
}
doSomeThing() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(66);
// reject(777);
}, 2000);
// });
}).then().then(123);
}
test() {
this.doSomeThing()
.then(function (val) {
console.log("first:", val);
return 88;
}, function (val) {
console.log(val, "reject");
return 588;
}).then(function (val) {
console.log("second:", val);
return new Promise(function (resolve, reject) {
console.log("inner promise");
resolve(555);
}).then().then(function (val) {
console.log(val, "***");
return new Promise(function (resolve, reject) {
console.log("inner inner promise");
resolve(555111);
}).then().then(function (val) {
console.log(val, "111***");
});
});
}).then(function (val) {
console.log("third:", val);
}).catch(function (e) {
console.log("catch", e);
});
}
}
console.log(1);
let testPromise = new TestMyPromise();
testPromise.test();
console.log(2);
package.json
{
"name": "test",
"version": "1.0.0",
"description": "npm init",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build1": "babel Promise.js -o build.js",
"build": "babel src -d dist",
"run-promise": "babel-node ./dist/promise/TestMyPromise.js",
"run-iterator": "babel-node ./dist/iterator/Test.js"
},
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "~7.9.0",
"@babel/node": "~7.8.7",
"@babel/preset-env": "^7.9.5",
"@babel/register": "~7.9.0",
"core-js": "^3.6.5"
}
}
.babelrc
{
"presets": [
["@babel/preset-env",
{
"corejs": 3,
"useBuiltIns": "usage"
}
]
]
}
使用 npm run build 进行编译
然后使用 npm run run-promise 执行。
运行结果如下:
1
2
first: 123
second: 88
inner promise
555 '***'
inner inner promise
555111 '111***'
third: undefined
由于使用了 import 语法,不能直接使用 node 运行。
具体原因可以参考:
SyntaxError: Unexpected token import