前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Promise 源码分析

Promise 源码分析

原创
作者头像
shirishiyue
修改2018-11-10 16:43:49
1.8K0
修改2018-11-10 16:43:49
举报
文章被收录于专栏:全栈码

从源码里分析 promise 奇特的特性。

        1、promise 基本概念就不介绍了,es6,解决套套问题。。

        2、本文主要记录下自己遇到的不懂的地方记录下,并没有全面去讲解。

        3、外部一种实现promise的源码:https://github.com/ygm125/promise/blob/master/promise.js

            先看个小例子的,

代码语言:javascript
复制
var promise = Promise.resolve(1);
promise.then(function(a){console.log(a,1);}).then(function(a){console.log(a,2)})
  //在浏览器console执行的结果:
    1 1
    undefined 2 
  //promise库执行的结果:
    1 1
    1 2

            显然,浏览器自己实现的 promise 和外部promise库的实现方案还是有细微差别的。但是这种差别不属于promise规范的范畴,你也可以实现自己更好用更多用途的。promise规范规定必须要异步的,浏览器实现的promise应该用的是浏览器内部的一些特性(不知道具体是什么),,,但是外部 promise 在 js 层面代码层面上怎么实现异步的呢,答案是:setTimeout()。。。

           

promise的三种状态:pending、fullfilled,rejected。

            promise构造函数的参数resolver,即是你自己的逻辑过程函数,该函数有两个参数,这两个参数会传与promise静态函数resolve和reject,你自己的逻辑过程函数逻辑(无论异步还是同步)写完后,记得在合适的地方调用这两个函数(这两个函数对应有自己的回调函数)即可,表示我的承诺已经给出来了。时机成熟时,调用处就是整个promise.then链条的发动处。

            promise.resolve和reject动作对应的回调函数需要你自己注册进去的。

            这个注册操作就是then函数了。

            但是为什么可以把回调函数放到未来去注册?

            理由是:异步(setTimeout异步或者浏览器自己的实现),确保了then()函数肯定在链条启动前就执行了!

then函数:

每then一次,都会返回一个新的promise对象。每次then的时候,首先判断调用者promise的状态:

  • 如果是pending,就把fullfill和reject回调注册进去;     如,wait(1000).then(function(x){console.log(x,1)}),初始状态是 pending
  • 如果是fullfill,就把fullfill后的值立即传给fullfill回调函数处理;     如,Promise.resolve(1).then(function(x){console.log(x,1)}),初始状态是 fullfill
  • 如果是reject,就把reject后的值立即传给reject回调函数处理。     如,Promise.reject(1)..then(function(x){console.log(x,1)}),初始状态是 reject

            这个then函数实现了一个特殊的地方见代码:68-77行,在于:你的fullfill回调有三种可能:

  • 是值,不是函数。那就不执行函数,把你传入的值当作当前promise fullfill状态的结果值,resolve一下。
  • 是函数、没有返回值。执行函数,promise当前值不变,resolve一下。
  • 是函数、有返回值。执行函数,把函数返回值当作promise的值,resolve一下。
  • 是函数、有返回值、返回值是thenable的(就是含有then方法的对象)。执行函数,给返回的proimse对象简单的then一下,这个then就是透传当前promise的值。

            then里面有递归,还不同于一般的递归,不是可以很直观理解。这个递归决定了这个then可以有多种多样的then链条。

举例子:

代码语言:javascript
复制
function doubleUp(value) {
 return value * 2;
}
function increment(value) {
 return value + 1;
}
function output(value) {
 console.log(value);// => (1 + 1) * 2
}
var promise = Promise.resolve(1);
promise
 .then(increment)
 .then(doubleUp)
 .then(output)
 .catch(function(error){
 // promise chain中出现异常的时候会被调用
 console.error(error);
 });

再举例子:

代码语言:javascript
复制
function sleep(msecond){
    return new Promise(function(a,b){
        setTimeout(a,msecond);
    });
}

//var promise = Promise.resolve(1);
var promise = sleep(1000);
promise.then(function(x){
    console.log(x,1);
    return Promise(function(a,b){
        b(x);
    });
}).then(function(x){console.log(x,2)})
.then(function(x){console.log(x,3)},function(x){console.log(x,4)})

还有更多各种嵌套的,都可以行的通。

▲ then链条如何保证顺序

1、promise1对象有了,显然是执行到setTimeout等待步骤了,状态是pending,timeout完成,立马就是fullfill状态并执行fullfill回调 函数func1

2、由于是异步,promise.then(func1)会在timeout完成前执行。

3、promise.then(func1)会新建promise2,即 new promies(resolver)。我们知道,在你的resovler代码里需要调用resovle函数才能使promise进入到setTimeout等待中。

4、链条连接点:func1里的新的promise2的resovler代码只有在promise状态为fullfill时才能执行。

5、也就是,只有promise1状态完成时,新的promise2才能进入setTimeout等待。

6、依次类推,,一环扣一环,,保证了链条有序执行。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档