• 【JS】把Promise手写明白!



    就是说,把这个最爱考的手写系列给它整明白!总结加理解加多复习,我就不信还能有什么别的花样!

    先介绍一下promsie的特点,三个状态pending、reject、fullfilled(resolved),状态只能从pending到另外两个,一经生成不可再改变,然后具有.then、.finally、.all、.race等函数进行使用

    • 抽象表达:

      Promise 是一门新的技术(ES6 规范)
      Promise 是 JS 中进行异步编程的新解决方案
      备注:旧方案是单纯使用回调函数

    • 具体表达:

      从语法上来说: Promise 是一个构造函数
      从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/
      失败的结果值

    • 为何要用promsie?
      1、指定回调函数的方式更加灵活
      2、支持链式调用,解决回调地狱的问题
      在这里插入图片描述

    //一个普通的promise的使用
    
    const p = new Promise((resolve,reject) => {
       
        setTimeout(() => {
       
            let n = Math.random()*100;
            if(n < 30){
       
                resolve(n);
            }else{
       
                reject('errrro发生错误');//返回的是一个prmise对象,且状态设置为失败,值为n
            }
        },1000)
    })
    
    console.log(p)
    
    p.then((value) => {
       
        console.log('成果'+value)
    },(err) => {
       
        console.log('shibai'+err)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    所以手写的就要实现基本的功能,一个构造promise,resolve、reject回调函数,返回promise还要支持then的调用

    手写Promsie函数

    const promiseA = new Promise( (resolve,reject) => {
       
        resolve(777);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 传入了一个函数,而且这个函数被立即执行,不仅如此,这个函数还会立即执行resolve和reject。说明构造函数里有resolve和reject方法。因此我们可以初步实现:
    • 每个promise都有一个状态可能为pending或resolved,rejected。而且初始状态都为pending。因此需要添加个status来表示当前promise的状态.。并且每个promise有自己的data。
    • 不管是Promise原型对象上的方法还是Promise函数对象上的方法 ,它们的执行结果都将返回一个Promise对象
    // 例1
    var promise = new Promise((resovle,reject)=>{
       
        
    })
    
    promise.then(resolve=>{
       },reject=>{
       })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这种情况,当状态为pending的时候,要把then里面的回调函数保存起来,所以需要一个callbacks数组,等prmsie里面的resolve或足额reject之后再执行;

    那么then函数是如何把传入的回调收集起来的,就是叛党当前promsie的状态是否为pending

    举一个例子

    // 例2
    var promise = new Promise((resolve,reject)=>{
       
        setTimeout(function () {
       
            resolve(1)
        })
    })
    
    promise.then(
        value=>{
       console.log(value)},
        err=>{
       console.log(err)}
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 先执行new Promise里的代码,然后发现个定时器,js线程将定时器交给定时器线程处理,2. 然后继续执行下面的代码,发现是then,而且当前的promise还是pending的状态。就把then里的回调函数放到callbacks中。
    • 5秒后定时器线程将定时器里的回调函数(也就是宏任务)放到消息队列中,js线程在消息队列里发现了这个宏任务,就把它拿来执行。- - 执行这个宏任务,就执行了resolve(1),此时promise的callbacks里的回调被执行。并将当前promise状态改为resolved。然后这个1也会被 保存到当前promise对象中

    那怎么实现resolve呢?依旧上面的描述,就知道resovle的功能是执行callbacks里的函数,并保存data,并将当前promise状态改为resolved。所以我们可以这么实现

    执行到then时,promise可能会是pending状态,此时就要把then里的回调函数保存起来,也可能会是resolved或者rejected状态,此时就不用把回调保存起来,直接执行onResolved或onRejected方法。注意是异步执行。而且是做为微任务的,这里我们简单的用setTimeout来实现就好了。

    function Promsie(callback) {
       
        this.state = PENDING;
        this.value = null;
        this.resolvedCallbacks = []
        this.rejectedCallbacks = []
    
        callback(value => {
       
            if(this.state == PENDING){
       
                this.state = RESOLVED
                this.value = value
                this.resolvedCallbacks.map(callback 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    视频理解学习笔记(三)
    docker 安装jenkins 跨域csrf
    Matlab自学笔记二十三:字符串的提取、替换、插入和删除
    keycloak~对框架中提供的Provider总结
    C# Event (1) —— 我想搞个事件
    Python 潮流周刊#53:我辈楷模,一个约见诺奖得主,一个成为核心开发者
    汇付国际为跨境电商赋能:做合规的跨境支付平台!
    SpringBoot整合Neo4j
    2020年09月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试
    HCIP---IS-IS协议
  • 原文地址:https://blog.csdn.net/zhaohb2016/article/details/126644736