关于promise的实现原理的思考
程序员文章站
2022-07-13 10:50:48
...
缘起
小编最近在刷题,看到了手写一个promise的文章,小编突然产生了几个问题
- promsie本身有没有暂停js进程功能
- promise是如何实现把值传入then中的
- promsie把值传入then中的时候,为啥会先执行promise以外的函数
promise实现
这里小编不具体写代码了,小编写个大概的就好,想看详细的大家可以去google搜索
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(executor) {
let self = this;
self.status = PENDING;
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value;
}
}
// reject代码此处省略
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
let promise2 = new Promise((resolve, reject) => {
if (self.status === FULFILLED) {
setTimeout(() => {
try {
onFulfilled(self.value);
} catch (e) {
reject(e);
}
});
}
}
}
以上就是一个简单版本的promise,虽然省略了很多代码,但是主要就是定义一个名为promise的构造函数,在其原型链上扩展then方法,把new Promise需要传递下去的值,放在原型链上,then可以通过原型链获得,重点来了,利用了原型链,就这么简单!
解答上面的问题
- promsie本身有没有暂停js进程功能
大家可以看上面的代码,promise本身不存在停止js运行功能!能暂停js运行的方法目前有以下几种:ajax的同步,await,生成器函数!说白了这个就是基于浏览器(c,c++,c#等)中断了单线程的js任务进程,迫使等待某个函数执行完毕! - promise是如何实现把值传入then中的
这个问题上面已经回答了,就是利用了原型链,从原型链获取值 - promsie把值传入then中的时候,为啥会先执行promise以外的函数,大家看到then中的那个定时器了嘛,可以去恶补下宏任务和微任务!
看图再次理解
如果promise本身具有中断js进程的功能,那么3出现的位置不会是1后面!因为then中的定时器所以,输出的顺序是4和2!
业务代码加深理解
// xx.js
console.log('start')
new Promise((resolve, reject) => {
// await 操作,再resolve()
}).then(v=>{})
console.log('end)
代码运行的时候,js的单线程会先输出start,然后promise运行到await停止,这个时候总线程是不会停止的,停止的只是await等待返回的那部分代码执行,总线程接着执行end,然后等到await返回的时候,线程再切到await那块,然后再执行resolve(),这就是我们看到的等待执行,then处理!
为啥在await等待的时候,不直接执行then呢,这里有一个很重要的概念,链式调用!
链式调用只会按照顺序来,如果前面等待,那么后面的方法会等待前面的执行完毕,才会调用
这个时候有的童鞋可能要问了,既然promise本身没法中断js代码执行,让页面等待,都是用了回调函数中的await等方式,那么promise的优势有啥?
promise的优势
- 保证了js单线程不会因为await等中断,充分利用了浏览器性能
- 链式调用和then方法保证了相关代码在then中处理,提升了可读性和写代码的愉悦性
尾声
小编不得不吐槽一句,自己想到很多问题,逼着自己去思考,虽然过程会很痛苦,但是一旦你思考完毕,你对这块的理解就会更加深入!写代码还是要多思考,越思考大脑才会转的越快!