用订阅/发布者模式解决异步函数结果依赖的问题

我们都知道node是基于事件无阻塞i/o模型的,所以说大部分函数都是以异步实现的,请看下面代码:

db.query(sql1, function (err, data) {
    //code
})

db.query(sql2, function (err, data) {
    //code
})

如果我们上述两个操作,结果之间没有什么联系,那很好,基于node的I/O无阻塞模型,每个操作都做着自己的事情,美滋滋~

但是在一些情况下这两个操作的结果有联系的,比如说第一个操作从数据库中取出一个人的姓,第二个操作从数据库中取出同一个人的名。

假设我们有一个需求就是我们要把这两个操作的结果组合起来变成一个人的姓名(这个操作貌似有点浮夸,嘻嘻),也就是说我们要组合成姓名这个操作必须是在姓和名都取到的情况下才能进行,可达鸭眉头一皱,发现事情并不简单。我们知道上述两个操作是异步操作,他们何时结束我们根本不能知道,只知道他结束时会执行回调函数。下面我们就用订阅发布者模式来解决它。请看下面代码:

var count = 0;
var results = {};
var done = function (key, value) {  //订阅,姓和名进行订阅
    results[key] = value;
    count++;

    if(count === 2) {
        //发布,也就是执行刚刚说的组成姓名的操作      var name = results.lastName + results.firtName;
    }

}

db.query(sql1, function (err, data) {
    //这里data我们假设是从数据库取到姓
    done("lastName", data);
})

db.query(sql2, function (err, data) {
    //这里data我们假设是从数据库取到名
    done("firstName", data);
})

这样一来,每个i/o完成都会执行done方法,把取到的数据存到results对象中,也就是订阅,而当订阅数等于2的时候,也就是两个操作都完成并且都把数据存在results中了,那么就可以发布,也就是执行组成姓名的操作。利用订阅/发布者模式实现多对一,基本完成了我们的需求,但是这样的代码是丑陋的,我们用闭包和偏函数把代码优化并且抽象一下,以适合更多的需求。改进代码如下:

var after = function (times, callback) {
    var count = 0,
        results = {};
    return function (key, value) {
        results[key] = value;
        count++;
        if(count === times) {
            callback();
        }
    };
};

//对闭包的引用
var done = after(times, render);

ps:利用node的events模块我们还可以实现订阅/发布者的多对多模式。

参考资料:深入浅出Node.js第4章

时间: 2024-10-09 01:18:52

用订阅/发布者模式解决异步函数结果依赖的问题的相关文章

js的订阅发布者模式

前两天在笔试一家知名企业的时候遇到一道题,要实现一个简单的订阅发布者模式,当时由于各种原因我没有做,提前交了卷.现在回想起来,还是有必要好好研究一发. 首先先说说订阅发布者模式,顾名思义,就是有订阅者和发布者,两者的功能,订阅是请求在某些事件(event)到达时可以通知它并执行对应的动作(action),而发布则相对的是向订阅告知事件(event)已经到达,你可以执行对应的动作(action)了.但是具体是怎么的一个思维呢,听我娓娓道来. 大家应该都知道nodeJs是由事件来驱动的,也就是每个函

订阅发布者模式简单版 和 高级计数器 哈哈!

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> // 订阅发布者模式简单版 function test(){ var obj = {} var on = function(name,cal

观察者模式和订阅/发布者模式(转)

在翻阅资料的时候,有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式还是存在差异,而我认为确实是存在差异的,本质上的区别是调度的地方不同. 观察者模式 比较概念的解释是,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口.具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法. 比如有个“天气中心”的具体目标A,专门监听天气变化,而有个显示天气的

js callback promise async await 几种异步函数处理方式

***callback  这个是最常用的也是最简单的 ,比如在ajax网络请求中,返回请求完成返回的数据 回调函数就是把一个函数当成另一个函数的参数,可以传递函数内的局部变量,也可以异步完成一些操作,在函数的实现里调用回调函数,在函数的调用里实现回调函数 // 回調函數的方式 閉包 可以獲取函數內部的局部變量 function testCallback(callback) { let a = 1; let b = 2; if (a < b) { callback && callbac

EventBus事件总线框架(发布者/订阅者模式,观察者模式)

一. android应用内消息传递的方式: 1. handler方式-----------------不同线程间传递消息. 2. Interface接口回调方式-------任意两个对象. 3. Intent进行组件间通信,广播方式. 二.单例比较好的写法: private static volatile EventBus defaultInstance; 构造函数应当是private,不应该是public 1 public static EventBus getDefault() { 2 if

Publisher/Subscriber 订阅-发布模式

Publisher/Subscriber 订阅-发布模式 本博后续将陆续整理这些年做的一些预研demo,及一些前沿技术的研究,与大家共研技术,共同进步. 关于发布订阅有很多种实现方式,下面主要介绍WCF中的发布订阅,主要参考书籍<Programming WCF Services>,闲话不多说进入正题.使用传统的双工回调(例子 http://www.cnblogs.com/artech/archive/2007/03/02/661969.html)实现发布订阅模式存在许多缺陷,主要问题是,它会引

Android 开源项目android-open-project工具库解析之(二) 高版本向低版本兼容,多媒体相关,事件总线(订阅者模式),传感器,安全,插件化,文件

六.Android 高版本向低版本兼容 ActionBarSherlock 为Android所有版本提供统一的ActionBar,解决4.0以下ActionBar的适配问题 项目地址:https://github.com/JakeWharton/ActionBarSherlock Demo地址:https://play.google.com/store/apps/details?id=com.actionbarsherlock.sample.demos APP示例:太多了..现在连google都

tableview加载图片的时候的优化之lazy(懒加载)模式and异步加载模式

iOS---tableview加载图片的时候的优化之lazy(懒加载)模式and异步加载模式举个例子,当我们在用网易新闻App时,看着那么多的新闻,并不是所有的都是我们感兴趣的,有的时候我们只是很快的滑过,想要快速的略过不喜欢的内容,但是只要滑动经过了,图片就开始加载了,这样用户体验就不太好,而且浪费内存.这个时候,我们就可以利用lazy加载技术,当界面滑动或者滑动减速的时候,都不进行图片加载,只有当用户不再滑动并且减速效果停止的时候,才进行加载.刚开始我异步加载图片利用SDWebImage来做

Spring基于事件驱动模型的订阅发布模式代码实例详解

代码下载地址:http://www.zuidaima.com/share/1791499571923968.htm 原文:Spring基于事件驱动模型的订阅发布模式代码实例详解 事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理解它的几个关键点: 首先是一种对象间的一对多的关系:最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方): 当目标发送改变(发布),观察者(订阅者)就可以接收到改变: 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的