Promise 作用
- Promise 表示异步操作的最终结果,解决异步回调、多层函数嵌套、并发的问题。
- 弊端:早期 IE 浏览器不支持。
- Promise 是一个类,new Promise 实例化传入 resolve,reject 去执行成功回调或失败回调。
- Promise 中的 then 回调返回普通值会将结果传递到下一次 then 的回调中。
Promise 实现
-
Promise 一个类,Promise 中会传入 executor 执行器,默认执行。
-
Promise 中的三种状态,pendding,resolved,rejected,一旦改变不会再次触发改变。
-
then 方法,onFulfilled 第一个参数成功的回调传成功的 value,onRejcted 第二个参数是失败的回调的 reason
- onFulfilled onRejcted 都是可选参数,如果不是函数会被忽略;
- 如果是函数,onFulfilled 必须在成功之后调用,value 作为函数的参数。onRejcted 必须在拒绝之后调用,reason 作为函数的参数。
- 一定不能在被拒绝或成功之前调用
- 一定不能被调用多次
- ...
-
如果 new Promise 中发生异常也会执行失败态
-
catch 方法实现
-
promise 链式调用实现
-
Promise.resolve,Promise.reject,Promise.all, Promise.finally
Promise 测试是否符合 A+ 规范
-
全局安装: npm install promises-aplus-tests -g
-
控制台执行命令: promises-aplus-tests ./promise.js
实现代码
promise.js文件:
const PENDDING = "PENDDING",
FULFILLED = "FULFILLED",
REJECTED = "REJECTED";
/**链式调用核心处理x p2的关系 */
const resolvePromise = (x, p2, resolve, reject) => {
if (x === p2) return reject("type error"); // 如果x和p2引用同一个对象TypeError
if ((typeof x === "object" && x != null) || typeof x === "function") {
let called;
/**捕获异常start */
try {
// 检测x上是否有then属性
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(y, p2, resolve, reject);
},
(e) => {
if (called) return;
called = true;
reject(e);
}
);
} else {
resolve(x); // 直接用x作为成功结果
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
/**捕获异常end */
} else {
resolve(x); // x一定是一个普通值此时p2的promise变成成功态
}
};
class Promise {
constructor(executor) {
this.status = PENDDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach((fn) => fn());
};
const reject = (reason) => {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejcted) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejcted =
typeof onRejcted === "function"
? onRejcted
: (err) => {
throw err;
};
let p2 = new Promise((resolve, reject) => {
/**链式调用 */
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功传入成功的原因
let x = onFulfilled(this.value);
resolvePromise(x, p2, resolve, reject);
} catch (error) {
reject(error);
}
}, 1000);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
// 失败传入失败的原因
let x = onRejcted(this.reason);
resolvePromise(x, p2, resolve, reject);
} catch (error) {
reject(error);
}
}, 1000);
}
if (this.status === PENDDING) {
// 等待状态时将成功和失败的回调函数收集起来
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
// 成功传入成功的原因
let x = onFulfilled(this.value);
resolvePromise(x, p2, resolve, reject);
} catch (error) {
reject(error);
}
}, 1000);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
// 失败传入失败的原因
let x = onRejcted(this.reason);
resolvePromise(x, p2, resolve, reject);
} catch (error) {
reject(error);
}
}, 1000);
});
}
/**链式调用 */
});
return p2;
}
// catch方法实现就是then的第一个参数是null
catch(onRejected) {
return this.then(null, onRejected);
}
// static静态方法通过类调用
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value); // 有等待效果
});
}
// static静态方法通过类调用
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason); // 不具备等待效果
});
}
}
/** promise-aplus-tests */
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
/** finally 无论如何都会被执行;应用场景:某些流程 无论成功或失败都执行。成功以外面为主失败走里面的。 */
Promise.prototype.finally = function (cb) {
return this.then(
(y) => {
return Promise.resolve(cb()).then(() => y);
},
(r) => {
Promise.resolve(cb()).then(() => {
throw r;
});
}
);
};
/** all 全成功才成功,有一个失败则进入失败。执行是有顺序的。 */
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
const arr = [];
let times = 0;
const processResult = (i, val) => {
arr[i] = val;
if (++times === promises.length) {
resolve(arr);
}
};
for (let i = 0; i < promises.length; i++) {
let val = promises[i];
if (typeof val.then === "function") {
val.then((v) => processResult(i, v), reject);
} else {
processResult(i, val);
}
}
});
};
module.exports = Promise;
index.js文件:
/** 可以调各种Promise方法测试promise.js源码中的内容这里列举一二*/
const Promise = require('./promise');
const p = new Promise((resolve, reject) => {
// resolve(1);
reject();
});
p.finally(() => {
console.log('怎么样都执行');
}).then(res => {
console.log(res, 1);
}, err => {
console.log(err, 2);
});
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.reject(3)]).then(res => {
console.log(res, '==');
}, err => {
console.log(err, '--');
})
控制台执行查看效果
执行命令:node index.js