• when 让你跳出异步回调噩梦 node.js下promise/A规范的使用


    其实关于promise 的博客,前端时间专门写了一篇关于 promise 规范的文章,promise规范 让 javascript 中的异步调用更加人性化.

    简单回忆下:

    promise/A规范定义的“Deferred/Promise”模型

    其实是实现了“发布/订阅”模型.

    通过Deferred对象发布事件,

    包括下面2种事件

    完成 --> resolve事件,

    失败 --> reject事件,

    通过Promise对象进行对应完成或失败的订阅

    类似于任务状态转变时事件被触发.

    将会对应的执行事件绑定函数.

    每个Promise任务都有三种状态:

    默认(pending)、完成(fulfilled)、失败(rejected)

    1.默认状态可以单向转移到完成状态,这个过程叫resolve,对应的方法是deferred.resolve(Value);

    2.默认状态还可以单向转移到失败状态,这个过程叫reject,对应的方法是deferred.reject(reason);

    3.默认状态时,还可以通过deferred.notify(message)来宣告任务执行信息,如执行进度;

    4.状态的转移是一次性的,一旦任务由初始的pending转为其他状态,就会进入到下一个任务的执行过程中。

    今天其实是想和大家分享下 when 这个 npm 包,或许未来不久你将会用到.

    github地址: https://github.com/cujojs/when

    我们通过一个具体的模拟示例来学习 when

    应用场景:

    假如我有一个服务,每天定时运行.

    做什么任务呢,就是去证券/银行站点读取当天的汇率信息,然后保存到自己的数据库.

    逻辑很简单:

    1. 查看当天是否有最新汇率信息

    2. 如果有,获取汇率信息

    3. 如果获取到,保存到本地数据库

    我们依次来定义3个方法:

    //获取汇率信息
    function get(callback){
        //具体请求url,分析dom全部省略,全当调用了下面的一个黑盒方法来实现
        yijiebuyi_util.getHtml('http://aaa.com/bbb',function(err,info){
            callback(err,info);
        });
    }
    //保存汇率信息
    function save(info,callback){
        //写入数据库方法忽略
        yijiebuyi_util.save(info,function(err,result){
            callback(err,result);
        });
    }

    OK,我们先来一把普通调用方法

    function main(callback){
        //获取汇率信息
        get(function(err,info){
           if(err){
               return callback(err,null);
           } 
           //保存汇率信息
           save(info,function(err,result){
               if(err){
                   return callback(err,null);
               }
               //回调保存状态
               callback(null,result);
           });
        });
    };

    如果业务更复杂的话,一层嵌套一层,看上去是不很带劲等到维护的时候可能就费劲了.

    有人说要使用 async 来控制,确实可行,而且我们一般也就是这样处理的.

    async 可以把整个流程控制住,比如串联执行,下一步执行函数使用上一步执行结果等.

    但是今天我们推荐大家一种看上去很优雅的解决方案.

    我们从处理流程跳出来,不要在流程上去控制业务,而是从每一个业务方法入手,让方法通过 when 构建一个promise规范的方法.

    我们还是要把上面的方法全部修改一下:

    首先安装,应用 when

    npm install -g when
    var when=require('when');
    function get(){
        var deferred = when.defer();
        yijiebuyi_util.getHtml('http://aaa.com/bbb',function(err,info){
            if(err)
                deferred.reject(err);
            else
                deferred.resolve(info);
                
            return deferred.promise;
        });
    }
    function save(info,callback){
        var deferred = when.defer();
        yijiebuyi_util.save(info,function(err,result){
            if(err)
                deferred.reject(err);
            else
                deferred.resolve(result);
                
            return deferred.promise;
        });
    }

    上面2个方法我们已经改装完毕,下面看看 main 方法中如何调用呢.

    function main(){
        get().then(save).catch(function(err){
            console.log(err);
        });
    }

    我们并没有在流程上控制业务逻辑处理顺序.而是像同步代码一样按照执行顺序调用即可,是不是很美好.

    then方法包括三个参数,

    onFulfilled、

    onRejected、

    onProgress

    promise.then(onFulfilled, onRejected, onProgress)

    从参数名你就可以发现这几个方法应该是事件处理函数.

    这也应了我们上面所说的, promise 本身就是一种事件发布/订阅模型.

    所以上面 then 里的三个函数相当于事件绑定函数.(就是观察者)

    当上一个任务被deferred.resolve(data) ,对应在本任务就会触发 onFulfilled 方法.

    当上一个任务被 deferred.reject(err) ,对应的本任务就会触发 onRejected 方法.

    任何一个任务, onFulfilled 或 onRejected 方法只能被触发一个,并且触发一次.

    我们上面main 方法中最后的 catch(function(err){.....}) 是怎么回事.

    when 提供了极其简单的传递错误机制,多个任务执行时,我们可以在最后一个任务定义onRejected 

    或者在 then 调用的最后用 catch 来捕捉错误.

    ***end***

  • 相关阅读:
    选择、插入、气泡排序
    JDBC基础学习(四)—数据库事务
    JDBC基础学习(三)—处理BLOB类型数据
    JDBC基础学习(二)—PreparedStatement
    JDBC基础学习(一)—JDBC的增删改查
    JavaWeb总结(十)—文件上传和下载
    JavaWeb总结(九)—过滤器
    JavaWeb总结(八)—EL表达式
    Java基础学习(三)—面向对象(上)
    MySQL学习笔记(一)—数据库基础
  • 原文地址:https://www.cnblogs.com/youlechang123/p/5602339.html
Copyright © 2020-2023  润新知