Promise 执行机制–原理–规范[通俗易懂]

Promise 执行机制–原理–规范[通俗易懂]Promise 执行机制–原理–规范

大家好,又见面了,我是你们的朋友全栈君。

读取本文章前相信你已经理解完毕promise的基本用法了,如果没有请前去参考阅读阮一峰老师的es6教程。

1.Promise异步与标准

首先promise是属于javescript的,javescript是一门单线程语言。javescript的多先程是用单线程模拟出来的。并不是完全意义上的多线程。

1.1 异步

promise是异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。

1.2 promiseA+

promise最早由社区提出并实现的,后经过一步步繁衍生息,在es6中为我们提供了一个原生的构造函数prosime, promise是根据并遵循统一的promiseA+标准来实现的。

2.Promise的状态与使用

Promise 对象存在以下三种状态:

~Pending(进行中)

~Fulfilled(已成功)

~Rejected(已失败)

2.1 Promise的立即执行/异步

看下面的代码

    setTimeout(() => {
      console.log('start one setTimeout')
    }, 0)
    const first = new Promise((resolve, reject) => {
      console.log('create one promise')
      const two = new Promise((resolve, reject) => {
        console.log('create two promise')
        setTimeout(() => {
          console.log('start two setTimeout')
        }, 0)
        resolve('two p2')
      })
      resolve('two p1')
      two.then((p2) => {
        console.log(p2)
      })
    })

    first.then(p1 => {
      console.log(p1)
    })
    console.log('after new Promise')
复制代码

Promise对象表示未来某个将要发生的事件,但在创建(new)Promise时,作为Promise参数传入的函数是会被立即执行的,即Promise的立即执行.

打印结果为 create one promise,create two promise,after new Promise,two p2,two p1,start one setTimeout,start two setTimeout

此处涉及到具体的js执行机制问题请移步 js执行机制

进行了两次事件循环,在最上部增加了一个setimeout为了更直观的表示队列问题,第一次事件循环先执行宏任务,发现第一个setimeout注册回调函数后放入Event Queque(下一轮任务队列),接着newpromise立即执行,输出 create one promise,接着执行 two 的newpromise 输出 create two promise, ,two的then放放入微任务队列,发现first的then,放入微任务队列(promise异步)。代码接着向下执行,输出after new Promise,宏任务执行结束。

此处的微队列的理解需要借助一部分promise的实现原理,promise对于then的回调做了渐进式兼容处理,常规状态下运用了Mutation​Observer.observe()()这个回调监听,进入微服务,如果采用setimout进行promise回调的话,then回调惠方式下一轮任务队列的。

再执行微任务,依次 two的then回调输出wo p2,再执行frist的then回调输出wo p1。第一轮事件循环结束。开始执行第二轮事件循环执行setimeOut按照在队列中的注册顺序依次输出start one setTimeout,start two setTimeout。

再来一个小例子。

 setTimeout(function() {
      console.log('1')
    }, 0)
    var p1 = new Promise(function(resolve, reject) {
      console.log('2')
      resolve(3)
    })
    setTimeout(function() {
      console.log('4')
    }, 0)
    p1.then(function(value) {
      console.log(value)
    })
    setTimeout(function() {
      console.log('5')
    }, 0)
复制代码

打印结果为 2,3,1,4,5

2.2 promise 的不可逆性

还是上面的代码我们做一点点小小的更改,在看输出结果。

setTimeout(() => {
      console.log('start one setTimeout')
    }, 0)
    const first = new Promise((resolve, reject) => {
      console.log('create one promise')
      const two = new Promise((resolve, reject) => {
        console.log('create two promise')
        setTimeout(() => {
          resolve('two p3')
          console.log('start two setTimeout')
        }, 0)
        resolve('two p2')
      })
      resolve('two p1')
      two.then((p2) => {
        console.log(p2)
      })
    })
    first.then(p1 => {
      console.log(p1)
    })
    console.log('after new Promise')
复制代码

打印结果你会发现two p3并没有打印出来,因为在执行setimeout之前two这个promise的状态已经由pedding变更了,延时回调执行的时候resolve已经不能改变他的状态了。

promise状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态。

3.promise与new promise 之resolve与reject

const first = Promise.resolve(1)
const second = Promise.resolve(first)
console.log(first === second)
复制代码

Promise打印输出为true.Promise.resolve(…)可以接收一个值或者是一个Promise对象作为参数。当参数是普通值时,它返回一个resolved状态的新的Promise对象,对象的值就是这个参数;当参数是一个Promise对象时,它直接返回这个Promise参数,对象的值就是接受的promise的参数。因此,p1 === p2。

–插一段Promise的实现原理—

Promise.resolve = function (value) {
    if (value instanceof Promise) {
        return value;
    }
    return new MyPromise(function (resolve, reject) {
        if (typeof value !== null && typeof value === 'object' && typeof value.then === 'function') {
            value.then();
        } else {
            resolve(value);
        }
    })
};
复制代码

从上可以看出当Promise.resolve执行的时候,会先判断传入的值,是否为promise的事例

const first = Promise.resolve(1)
 const second = new Promise(function(resolve, reject) {
  resolve(1)
 })
console.log(first === second)
复制代码

输出 false,因为通过new方式创建的promise是一个新的对象

var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p4 = new Promise(function(resolve, reject){
  resolve(p1);
});

p4.then(function(value){
  console.log('p4=' + value);
});

p2.then(function(value){
  console.log('p2=' + value);
})

p1.then(function(value){
  console.log('p1=' + value);
})

复制代码

控制台输出:

p2=1 p1=1 p4=1 Promise回调函数中的第一个参数resolve,会对Promise执行”拆箱”动作。即当resolve的参数是一个Promise对象时,resolve会”拆箱”获取这个Promise对象的状态和值,但这个过程是异步的。p4″拆箱”后,才会输出,所以p4的then最先调用,但在控制台上确实最后输出的。

参考借例 一个Promise面试题 —-八段代码掌握promise

转载于:https://juejin.im/post/5cbebda2f265da039955dd42

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106859.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python缩进格式错误的是_python 缩进错误,

    展开全部要求严2113格的代码缩进是python语法的一大特色,就像C语言5261家族(C、C++、Java、C#等等)中的花括4102号一1653样重要,在大多数场合还有必要。在很多代码规范里面也都有要求代码书写按照一定的规则进行换行和代码缩进,但是这些要求只是纯粹是方便人(程序员)来阅读、使用或修改的,对于编译器或者解释器而言,完全是视而不见的。但是对Python解释器而言,每行代码前的缩进都…

    2022年4月12日
    35
  • java和html_如何区别html和html5

    java和html_如何区别html和html5JSP和HTMLJSP代表JavaServerPages;它主要用于开发动态网页,文件的扩展名为.jsp。JSP的主要优点是程序员可以在HTML中插入Java代码;使用JSP标签插入Java代码。程序员可以编写<%标签来启动Java代码,并在Java代码的末尾写入%>标签。JSP允许在HTML文件中插入Java代码HTML代表超文本标记语言。它是众所周知的用于开发网页的标记语言,有助于构建网页结构。JSP和HTML之间的区别1、采用的技术不同HTML是客户端技术,提供

    2025年8月13日
    4
  • 免费申请国外免费域名超详细教程「建议收藏」

    免费申请国外免费域名超详细教程「建议收藏」1.首先申请免费域名网站:https://my.freenom.com/domains.php2.填入域名,这里我们以xcflag为列(尽量选择复杂一点的或者五个字母以上的域名,因为简单的有些域名是需要收费的),点击检查可用性。3.可以看到很多免费的域名(用的谷歌翻译插件,翻译有时候不是很准确,free翻译过来应该是免费而不是自由,之后会写一些关于谷歌插件的笔记,详细讲解)4.我们选择xcflag.tk点击立即获取,稍等一会点击购物车查看绿色按钮5.默认三个月试用,这里下拉框我们选择十二个月

    2022年6月30日
    156
  • Java的注解

    Java的注解一、注解的概念:注解并不是一开始就有的,JDK5之前是没有注解的,JDK5及其以后JDK版本才开始支持Java注解!Java注解(Annotation)也叫做元数据,以@注解名在代码中存在,它是一种在源代码中标注的特殊标记,可以标注源代码中的类、属性、方法、参数等代码,主要用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。1.1Java注解按照含有参数的个数分为三种:不带参数,语法结构为:@Annotation,例如@FunctionalInterface;带一个参数的注解,语

    2022年7月9日
    21
  • Java到底好不好学「建议收藏」

    Java到底好不好学「建议收藏」Java到底好不好学答案是:不难学。很多人都以为编程是个很高深的东西,其实不然,真正学习了你会发现编程比你高中学的数理化要简单的多。说它不难呢,如果学深入了,还算有很多东西要学习,比如你学Java,后面可能要了解计算机组成原理、操作系统等底层知识,当然这些知识只要用心去了解,还是我们一般人都可以理解的。Java学习途径说到一门知识或技能好不好用,学习途径是很重要的,如果没有学习途径,有的时候一个很简单的知识都要花很久搞明白。我们是踩在巨人的肩上的,老一辈人给我留下了很多宝贵知识以及经验,..

    2022年7月7日
    24
  • 博客中KindEditor配置[通俗易懂]

    博客中KindEditor配置[通俗易懂]1.下载 KindEditor2.放在static/js下3.在admin.py中配置文件:4.在static/js/kindeditor下配置config.js文件首先在kindedito官网文档中,找到代码:根据代码提示编辑:5.编辑图片和文件上传代码:#-*-coding:utf-8-*-fromdjango.httpimp…

    2022年10月12日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号