• 理解Promise的3种姿势


    译者按: 对于Promise,也许你会用了,却并不理解;也许你理解了,却只可意会不可言传。这篇博客将从3个简单的视角理解Promise,应该对你有所帮助。

    为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。

    示例1中,asyncFunc()函数返回的是一个Promise实例:

    // 示例1
    function asyncFunc()
    {
    return new Promise(function(resolve, reject)
    {
    setTimeout(function()
    {
    resolve('Hello, Fundebug!');
    }, 100);
    });
    }
     
    asyncFunc()
    .then(function(x)
    {
    console.log(x); // 1秒之后打印"Hello, Fundebug!"
    });

    1秒之后,Promise实例的状态变为resolved,就会触发then绑定的回调函数,打印resolve值,即”Hello, Fundebug!”。

    那么,什么是Promise呢?

    • Promise调用是阻塞的
    • Promise中保存了异步操作结果
    • Promise是一个事件

    Promise调用是阻塞的

    示例2可以帮助我们理解阻塞

    // 示例2
    function asyncFunc()
    {
    return new Promise(function(resolve, reject)
    {
    setTimeout(function()
    {
    resolve('Hello, Fundebug!');
    }, 1000);
    });
    }
     
    async function main()
    {
    const x = await asyncFunc(); // (A)
    console.log(x); // (B) 1秒之后打印"Hello, Fundebug!"
    }
     
    main();

    以上代码是采用Async/Await语法写的,与示例1完全等价。await的中文翻译即为”等待”,这里可以”望文生义”。因此,相比于使用Promise实现,它更加直观地展示了什么是阻塞

    • (A)行: 等待asyncFunc()执行,直到它返回结果,并赋值给变量x
    • (B)行: 打印x

    事实上,使用Promise实现时,也需要等待asyncFunc()执行,之后再调用then绑定的回调函数。因此,调用Promise时,代码也是阻塞的。

    Promise中保存了异步操作结果

    如果某个函数返回Promise实例,则这个Promise最初相当于一个空白的容器,当函数执行结束时,其结果将会放进这个容器。示例3通过数组模拟了这个过程:

    // 示例3
    function asyncFunc()
    {
    const blank = [];
    setTimeout(function()
    {
    blank.push('Hello, Fundebug!');
    }, 1000);
    return blank;
    }
     
    const blank = asyncFunc();
     
    console.log(blank); // 打印"[]"
     
    setTimeout(function()
    {
    const x = blank[0]; // (A)
    console.log(x); // 2秒之后打印"Hello, Fundebug!"
    }, 2000);

    开始时,blank为空数组,1秒之后,”Hello, Fundebug!”被添加到数组中,为了确保成功,我们需要在2秒之后从blank数组中读取结果。

    对于Promise,我们不需要通过数组或者其他变量来传递结果,then所绑定的回调函数可以通过参数获取函数执行的结果。

    Promise是一个事件

    示例4模拟了事件:

    // 示例4
    function asyncFunc()
    {
    const eventEmitter = {
    success: []
    };
     
    setTimeout(function()
    {
    for (const handler of eventEmitter.success)
    {
    handler('Hello, Fundebug!');
    }
    }, 1000);
     
    return eventEmitter;
    }
     
    asyncFunc()
    .success.push(function(x)
    {
    console.log(x); // 1秒之后打印"Hello, Fundebug!"
    });

    调用asyncFunc()之后,sucesss数组其实是空的,将回调函数push进数组,相当于绑定了事件的回调函数。1秒之后,setTimeout定时结束,则相当于事件触发了,这时sucess数组中已经注册了回调函数,于是打印”Hello, Fundebug!”。

    Promise成功resolve时,会触发then所绑定的回调函数,这其实就是事件。

    参考


  • 相关阅读:
    【业务自动化】iTop,全面支持ITIL流程的一款ITSM工具
    【Hadoop】HDFS源码解读
    【Hadoop】Hadoop RPC框架线程模型
    电商网站项目(一)用户模块---门户
    jdk1.5后枚举类的定义规则
    回顾static与final的作用
    @Springboot搭建项目controller层接收json格式的对象失败
    把一个文件中所有文件名或者文件路径读取到一个txt文件,然后在matlab中读取
    springboot用mybatis-generator自动生成mapper和model
    hibernate、mybatis、spring data 的对比
  • 原文地址:https://www.cnblogs.com/fundebug/p/7596273.html
Copyright © 2020-2023  润新知