问题
function Promise(xxx) {
xxx
return xxx
}
var promise = new Promise(function(x, y){
setTimeout(() => {
x(101)
}, 3000)
})
promise.then((z) => {
console.log(z) // 101
})
解决思路
- 从上面使用自己实现的
Promise
时,可以看到传入的参数是一个函数,那么确定Promise
的参数类型是Function
,同时它返回的内容里还有一个then
方法,它也接受一个函数作为参数,根据对Promise
的了解,它应接受两个函数:
function Promise(fn) {
...
return {
then: function(successFn, errorFn) {
return undefiend; //如果不写默认return undefined,这里我们只做一次then,如果要用then链,可能需要递归调用
}
}
}
- 同时我们需要去执行传进来的这个函数,它实际上有两个函数作为参数,则必然:
function Promise(fn) {
fn.call(undefined, successNotify, errorNotify); // fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
function Promise(fn) {
function successNotify() {}
function errorNotify() {}
fn.call(undefined, successNotify, errorNotify); // fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
- 为了让fn的处理函数能够正确反映Promise的状态,需要添加一个状态变量:
function Promise(fn) {
let status = 'pending';
function successNotify() {
status = 'resolved';
}
function errorNotify() {
status = 'rejected';
}
fn.call(undefined, successNotify, errorNotify); // fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
return undefined;
}
}
}
- 接下来我们要处理then传进来的函数,如果成功你那个解决了,就要处理then传进来的成功函数,否则要处理失败函数,因此用两个单独的队列放传进来的函数:
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
}
function errorNotify() {
status = 'rejected';
}
fn.call(undefined, successNotify, errorNotify); //fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不写默认return undefined,这里我们只做一次then,如果要用then链,可能需要递归调用
}
}
}
- 只有在处理好之后才会处理then里面传递的内容,新增一个对then的处理函数:
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
handleThen.apply(undefined, arguments);
}
function errorNotify() {
status = 'rejected';
handleThen.apply(undefined, arguments);
}
function handleThen() {
if (status === 'resolved') {
for (let i = 0; i < successArray.length; i++) {
successArray[i].apply(undefined, arguments);
}
} else if (status === 'rejected') {
for (let i = 0; i < errorArray.length; i++) {
errorArray[i].apply(undefined, arguments);
}
}
}
fn.call(undefined, successNotify, errorNotify); //fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不写默认return undefined,这里我们简化,只做一次then,如果要用then链,可能需要递归调用
}
}
}
- 为了确保回调是异步执行的,用setTimeout裹一层:
function Promise(fn) {
let status = 'pending';
let successArray = [];
let errorArray = [];
function successNotify() {
status = 'resolved';
handleThen.apply(undefined, arguments);
}
function errorNotify() {
status = 'rejected';
handleThen.apply(undefined, arguments);
}
function handleThen() {
setTimeout(() => {
if (status === 'resolved') {
for (let i = 0; i < successArray.length; i++) {
successArray[i].apply(undefined, arguments);
}
} else if (status === 'rejected') {
for (let i = 0; i < errorArray.length; i++) {
errorArray[i].apply(undefined, arguments);
}
}
});
}
fn.call(undefined, successNotify, errorNotify); //fn接受两个函数作为参数
return {
then: function(successFn, errorFn) {
successArray.push(successFn);
errorArray.push(errorFn);
return undefined; // 如果不写默认return undefined,这里我们简化,只做一次then,如果要用then链,可能需要递归调用
}
}
}