乐趣区

js手动实现promise

let promise = new Promise((resolve111, reject) => {
// 这里放入我们要执行的函数,可能是同步,也可能是异步, 这里我们就来写一个异步的执行
setTimeout(() => {
resolve111(‘hello’);
}, 100)
})

promise.then(data => {
console.log(data);
return new Promise(function(res, rej) {
setTimeout(function() {
console.log(2);
res();
}, 100)
})
}, err => {console.log(err)})

promise 的执行流程如如下:

var i = 1
function Promise(fn) {
this.id = i++;
this.status = ‘PENDING’;
this.value = null;
this.onResolvedCallback = [];
this.onRejectedCallback = [];
// 构造函数内调用函数(调用函数改变 this 的指向)
// resolve 和 reject 的 this 都是当前的 Promise 对象。使用 bind 方法不会立即执行函数,而是返回一个新的函数
fn.call(this, this.resolve.bind(this), this.reject.bind(this))
}

Promise.prototype = {
constructor: Promise,
then: function(onfulfilled, onrejected) {
var obj = {
onfulfilled: onfulfilled,
onrejected: onrejected
}
// 新来一个 Promise 对象,让其存储这些
// 并且能根据不同的 Promise 去 then
obj.promise = new this.constructor(function() {});
// 保存接下来的子 Promise
// 建立一个与下一个 Promise 之间的关系
if (this.status === ‘PENDING’) {
this.onResolvedCallback.push(obj);
} else {
this.onRejectedCallback.push(obj);
}
return obj.promise;
},
resolve: function(data) {
this.status = ‘FULFILLED’;
this.value = data;
this.onResolvedCallback.forEach(item => {
let p = item.onfulfilled(this.value);
// 如果 p 是一个 Promise 的话,我们需要让他继续执行
// 把后续(item.promise)的 onResolvedCallback 交给这个 p
if (p && p.constructor === Promise) {
// 把下一个作为 then 链接的 onResolvedCallback 移交 p 的 onResolvedCallback
p.onResolvedCallback = item.promise.onResolvedCallback;
}
});
},
reject: function(err) {
this.status = ‘REJECTED’;
this.value = err;
this.onRejectedCallback.forEach(item => {
let p = item.onfulfilled(this.value);
if (p && p.constructor === Promise) {
p.onRejectedCallback = item.promise.onRejectedCallback;
}
});
}
}

then 方法需要返回一个新的子 Promise,并且前后的 Promise 需要建立联系,才能决定他们的执行顺序。这里用 id 标识每个 promise。
Promise 链式操作中,执行顺序是如何保证的
每个 promise 后面链一个对象该对象包含 onfulfiled,onrejected, 子 promise 三个属性,当父 promise 状态改变完毕, 执行完相应的 onfulfiled/onfulfiled 的时候呢,拿到子 promise, 在等待这个子 promise 状态改变,再执行相应的 onfulfiled/onfulfiled。依次循环直到当前 promise 没有子 promise

如何让异步的 value 在 thenable 函数中拿到
将 resolve/reject 函数和 onfulfiled/onrejected 放入同一个对象 (promise 对象) 里面,resolve/reject 的时候将 value 设置 this.value=xxx。onfulfiled/onrejected 执行的时候呢,onfulfiled(this.value)即可。

在这里避免头晕,解释一下,onfulfilled 和 onrejected 指的是 then 里面的两个函数。
状态机制切换
如图所示,状态只能由 pengding–>fulfilled,或者由 pending–>rejected 这样转变。

只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

退出移动版