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 条评论
登录 后参与评论

相关文章

来自专栏xx_Cc的学习总结专栏

iOS-RunLoop充满灵性的死循环

3788
来自专栏码匠的流水账

聊聊eureka server的response cache

eureka-core-1.8.8-sources.jar!/com/netflix/eureka/resources/ApplicationResource....

663
来自专栏ios 技术积累

iOS RunLoop

RunLoop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件(比如说触摸事件、UI刷新事件、定时器事件、Selector事件),从而保持程序的持续运...

662
来自专栏向治洪

android任务栈

1.启动任务栈     第一种,动作设置为“android.intent.action.MAIN”,类别设置为“android.intent.category...

1725
来自专栏不会写文章的程序员不是好厨师

日志那些事儿——slf4j集成logback/log4j

在日志Logger漫谈中提到了slf4j仅仅是作为日志门面,给用户提供统一的API使用,而真正的日志系统的实现是由logback或者log4j这样的日志系统实现...

1032
来自专栏草根专栏

使用两种方法让 ASP.NET Core 实现遵循 HATEOAS 结构的 RESTful API

HATEOAS(Hypermedia as the engine of application state)是 REST 架构风格中最复杂的约束,也是构建成熟 ...

50211
来自专栏帘卷西风的专栏

关于cocos2dx之lua使用TableView

在手机游戏的开发中,滚动是一项非常重要的操作,而cocos2dx中使用的最广泛的就属于TableView了,不过由于cocos2dx的接口比较晦涩,所以需要一...

892
来自专栏美团技术团队

【美团技术团队博客】Dive into Category

本文系学习Objective-C的runtime源码时候整理所成,主要剖析了category在runtime层的实现原理以及和category相关的方方面面,包...

3456
来自专栏朱慕之的博客

RunLoop

RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理。之...

922
来自专栏iOS技术杂谈

iOS多线程——你要知道的RunLoop都在这里你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里

你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里 转载请注明出处 https://cloud.tencent.co...

4138

扫码关注云+社区