Promise 实践

作者:何方舟

promise已经是成为我们解决回调炼狱的常用方案,而且已经得到官方标准支持,如果你刚刚开始使用Promise,本文将帮助你了解几个常见的几个Promise的使用场景

使用Promise可以让程序的可读性变得更好。如下面这样的代码:

var p = Promise.resolve();
      p.then(getUserInfo)
       .then(getGroupInfo)
       .then(getTaskInfo)
       ...

function getUserInfo(){
    
   console.log('getUserInfo start');
   return new Promise((resolve,reject)=>{
       setTimeout(()=>{
            var userInfo = {
                name  'adamchuan'
            };
            resolve(userinfo);
            console.log('getUserInfo end');
       },1000);
   });
}

function getGroupInfo(userinfo){
   console.log('getGroupInfo start');
   return new Promise((resolve,reject)=>{
       setTimeout(()=>{
            console.log('4');
            var groupInfo = {
                name : 'jdc'
            }
            console.log('getGroupInfo end');
            resolve(groupInfo,userinfo);
       },1000);
   });
}

function getTaskInfo(groupInfo,userinfo){
   console.log('getTaskInfo start');
   return new Promise((resolve,reject)=>{
       setTimeout(()=>{
        var taskInfo = {
            name : 'rebuild'
        };
        console.log('getTaskInfo end');
        resolve();
       },1000);
   });
}

/* 输出结果 
 getUserInfo start
 getUserInfo end
 getGroupInfo start
 getGroupInfo end
 getTaskInfo start
 getTaskInfo end
*/

如上面代码所示,我们可以很清楚的理解到程序执行的顺序是

  1. 得到userinfo
  2. 得到groupinfo
  3. 得到taskinfo

这样的代码在许多Promise示例中都可见,但这里有一点需要特别注意一下,

每次调用then都会返回一个新的Promise,如果then中的申明的方法没有返回一个Promise,那么会默认返回一个新的

处于fulfilled的Promise,之后添加的then中的方法都会立即执行,

如下面代码所示,如果在上面的代码中没有返回一个promise,输出的结果就变成 1 3 5 2 4 6了。

当要在使用链式Promise时,请在then传入的方法中返回一个新的Promise。

var p = Promise.resolve();
      p.then(getUserInfo)
       .then(getGroupInfo)
       .then(getTaskInfo)
       ...

function getUserInfo(){
   console.log('1');
   new Promise((resolve,reject)=>{
       setTimeout(()=>{
        console.log('2');
        resolve();
       },1000);
   });
}

function getGroupInfo(){
   console.log('3');
   new Promise((resolve,reject)=>{
       setTimeout(()=>{
        console.log('4');
        resolve();
       },1000);
   });
}

function getTaskInfo(){
   console.log('5');
   new Promise((resolve,reject)=>{
       setTimeout(()=>{
        console.log('6');
        resolve();
       },1000);
   });
}

/* 输出结果 
 getUserInfo start
 getGroupInfo start
 getTaskInfo start
 getUserInfo end
 getGroupInfo end
 getTaskInfo end
*/

另外一个需要注意的是,resolve传递给下个then方法的值只能有一个,上面 getTaskInfo方法中是无法获取到userInfo的值,所以如果有多个值需要放在一个数据集合(Array,Object,Map,Set)中传入下个方法)。

function getTaskInfo(groupInfo,userInfo){ /* userInfo为undefined */
   console.log(groupInfo); // { name : 'jdc'}
   console.log(userInfo);  // undefined
}

原生API函数的Promise化

大部分原生的API函数并不支持Promise,还是基于回调来使用的,所以需要把一些方法Promise化,类似trunk化。

下面一个例子把原生中的定时器setTimeout ,进行Promise化。

function timer(fn,time){
    return function(){
        return new Promise( (resolve,reject)=>{
            setTimeout(function(){
                fn();
                resolve();
            },time);
        });
    }
}
Promise.resolve()
    .then(
        timer(function () {
            console.log('1')
        }, 1000)
    )
    .then(() => {
        console.log('2');
    });

Promise化本质上都属于一种curry化。curry化是指,把需要传递多参数的函数生成一个新的函数,如上代码 先通过执行 timer得到一个新的函数,该函数会返回一个Promise,这样就完成了Promise化。

 timer(function () {
    console.log('1')
 }, 1000) 

原文链接:http://ivweb.io/topic/58204de262a899565c1c8914

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

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

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏React

React和Redux——状态管理Flux和Redux

在强调组件化的React中,我们需要以高内聚、低耦合的原则设计高可复用性的组件。因此渲染组件的数据由两部分组成,一个是由父组件传入的Props参数、一个是组件的...

2027
来自专栏跟着阿笨一起玩NET

ASP.NET 尖括号 百分号 井号 等号 的用法

362
来自专栏林德熙的博客

win10 uwp 异步进度条 圆形进度条

进度条可以参见:http://edi.wang/post/2016/2/25/windows-10-uwp-modal-progress-dialog

361
来自专栏白驹过隙

ACE - ACE_Task源码剖析及线程池实现

3518
来自专栏一个会写诗的程序员的博客

一段探索React自建内部构造的旅程

在先前的文章里我们涵盖了React基本原理和如何构建更加复杂的交互组件。此篇文章我们将会继续探索React组件的特性,特别是生命周期。

754
来自专栏wym

Windows创建窗口详解+代码---十天教会你俄罗斯方块

代码地址:https://blog.csdn.net/qq_41603898/article/details/80968266

521
来自专栏lonelydawn的前端猿区

一款轻量级树形控件EasyTreeview

使用方法 引入 <link rel="stylesheet" type="text/css" href="./css/index.min.css"> <div ...

3179
来自专栏web前端教室

vue.js的条件渲染,其实就是模板里面写if else

模板里面写逻辑判断在早期只有二种方法,一是用什么插件来搞;二是自己写一个模板然后正则匹配判断结果去替换字符串。其实这二种方法都是一样的,因为什么模板的插件十有八...

1907
来自专栏aoho求索

Spring中的事件驱动模型(一)

事件驱动模型 事件驱动模型通常也被理解成观察者或者发布/订阅模型。 是一种对象间的一对多的关系; 当目标发送改变(发布),观察者(订阅者)就可以接收到改变; ...

3025
来自专栏Java后端技术

获得同级iframe页面的指定ID元素的几种实现方法

注:window.frames("iframe的name")、document.frames("iframe的name")和window.frames["ifr...

852

扫码关注云+社区