Promise诞生记

Promise

前端近年的兴起,有大部分是因为 NodeJS 的诞生,而 NodeJS 是个适用于 异步IO 密集型的语言,一些基于 NodeJS 的框架,比喻 KOA2、Adonis 就有大量的 asyncawait 语法,async的函数的返回值就是 Promise 对象,我们可以用 asyncawait 语法,写出优雅的异步代码,来替换难看且难维护的回调函数。

这里我们会渐进式的来创建一个 Promise 的实现,如果,你还不了解 Promise ,赶快移步 Promise 了解学习,当然这个实现会符合 Promise/A+ 规范,JavaScript 中有很多第三方的 Promise 库,bluebird 就是一个第三方 Promise 类库,相比其它第三方类库或标准对象来说,其有以下优点:功能更齐全而不臃肿、浏览器兼容性更好,大家可以了解下。


废话不多说,直接开干。。。 😠

定义 Promise 类型

一个简单 Promise 语法,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const promise = new Promise(function(resolve, reject) {
// ... doSomething

if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});

promise.then(function(value) {
// success
}, function(error) {
// failure
});

实现 resolve 和 then

首先我们以上 👆 的语法,自己定义一个 Promise 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Promise(fn) {
var callback = null;
//实现 then 方法 , 先一步一步来,实现传一个参数 -- resolve
this.then = function(cb) {
callback = cb;
};

//实现 resolve , value:异步操作的最终值
function resolve(value) {
callback(value);
}
//执行 function 参数
fn(resolve);
}

一个简单的实例写好了,然后,来用一下,看看 👀 结果如何

1
2
3
4
5
6
7
const p = new Promise(function(resolve){
resolve(66);
});

p.then(function(value){
console.log(value);
});

执行结果是:callback is not a function

修改 callback 为异步

这里就遇到一个问题:

发现 resolve()then() 之前调用,在 resolve() 被调用的时候, callback 还是 null ,我们的代码是同步的,而不是异步的。
如是,想办法解决掉这个问题,就是利用 setTimeout , 把 callback 加入异步队列

代码如下 👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Promise(fn) {
var callback = null;
//实现 then 方法 , 先一步一步来,实现传一个参数 -- resolve
this.then = function(cb) {
callback = cb;
};

//实现 resolve , value:异步操作的最终值
function resolve(value) {
// 用 setTimeout 把 callback 加入到异步队列,这样就会,先执行 then() 方法
setTimeout(function(){
callback(value);
},1)
}
//执行 function 参数
fn(resolve);
}

然后,再来用一下,看看 👀 结果如何

1
2
3
4
5
6
7
const p = new Promise(function(resolve){
resolve(66);
});

p.then(function(value){
console.log(value);
});

执行结果是:66

未完待续。。。

本文结束感谢您的阅读

本文标题:Promise诞生记

文章作者:李少颖(persilee)

发布时间:2018年04月18日 - 01:04

最后更新:2018年05月22日 - 02:05

原始链接:https://h.lishaoy.net/createPromise.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!