记第一次手写Promise
之前做项目的时候,一般使用AJAX请求数据,相信大多数同学都会使用.then来处理一些异步任务,但是这样的话可能会发生回调地狱,脑子混乱… 直到有一天,我看到了这段代码
function asyncFn1() {
console.log('asyncFn1 run');
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('asyncFn1执行完了');
}, 2000)
})
}
function asyncFn2() {
console.log('asyncFn2 run');
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('asyncFn2执行完了');
}, 1000)
})
}
function normalFn3() {
console.log('normalFn3 run');
}
// 这样就比较好理解了,当asyncFn1re的resolve()执行的时候,才会执行.then()里面的函数,同理
asyncFn1().then(asyncFn2).then(normalFn3);
(可能是为了更好的链式使用.then,所以一般都使用函数返回一个Promise,而不是直接声明Promise???)
不管怎么说,我们今天就是要手写一个Promise,准备好了吗?
我们首先来看Promise的正常使用方法
// Promise在创建的时候,接收一个函数对象(被称为excutor),这个函数有两个参数
let p = new Promise((resolve, reject) => {
console.log('这个函数是立即执行的');
setTimeout(() => {
resolve('异步操作得到的数据') // 可以把这里换成reject(’失败‘)试试
}, 1)
})
// Promise的实例还有一个then方法,也接收两个参数,第一个参数为’成功时的回调‘,第二个参数为’失败时的回调‘
p.then((data) => {
console.log('success:',data);
}, (data) => {
console.log('eorr:',data);
})
当resolve()方法被执行的时候,就会执行then中的第一个函数,当reject()方法被执行的时候,就会执行then中的第二个函数
现在,我们尝试着自己实现一个Promise,暂且称为MyPromise
// 还是使用ES5的语法来写
// 刚刚上文中提到,我们在new Promise的时候,传入一个function对象,称之为excutor
function MyPromise(excutor) {
var self = this;
self.resolve = '';
self.reject = '';
self.value = '';
self.reason = '';
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
// 3.这里有一个隐藏的知识点,new Promise创建的实例有一个默认的状态 --- ‘pending’,只有在resovle或者reject的时候才会改变这个状态,且改变之后不能创新修改
function resolve(value1) {
if (self.status === 'pending') {
self.status = 'resolved';
self.value = value1;
self.onResolvedCallbacks.forEach((callback) => {
callback()
})
}
}
function reject(value2) {
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = value2;
self.onRejectedCallbacks.forEach((callback) => {
callback()
})
}
}
excutor(resolve, reject); // 1.传进来的这个excutor是立即执行的
}
// 2.刚刚上文中明显可以看到,Promise的实例p,有一个then方法,且接收两个参数,分别是'成功回调','失败回调'
MyPromise.prototype.then = (resolve, reject) => {
let self = this;
if (self.status === 'resovled')
// 4. 我们会更具Promise的状态值去决定调用then中的第一个,还是第二个函数,并且赋值
resolve(self.value1);
}
if (self.status === 'rejected') {
reject(self.value2);
}
// 5.执行的时候,发现,有两个问题 1.异步调用顺序不正确 2.多次使用.then(不是链式)的时候会有问题
// 所以,我们肯定在将多次的then里面要做的事情,在'pending'状态下,先放在数据中先存储起来,等'resolve'的时候,再调用
if (self.status === 'pending') {
self.onResolvedCallbacks.push(() => resolve(self.value));
self.onRejectedCallbacks.push(() => resolve(self.reason));
}
}
写到这里,应该足够理解Promise的原理了,但是现在还是是存在一些问题的,比如,Promise的链式调用,我们目前还没有实现的,就是文章首页的那种写法,但是个人不是很喜欢这样的写法,之后在开发中可能会多尝试一下 async await的开发方式(听说很香,也很容易从字面上理解)
function asyncFn1(){
console.log('asyncFn1');
return new Promise(function(resolve){
setTimeout(function(){
resolve('123');
}, 2000)
})
}
function asyncFn2() {
console.log('asyncFn2');
return new Promise(function(resolve){
setTimeout(function(){
resolve('456');
}, 2000)
})
}
async function asyncFn () {
var a = await asyncFn1();
var b = await asyncFn2();
console.log(a,b)
}
asyncFn();
详情可以参考:https://www.jianshu.com/p/b4fd76c61dc9