如何收集多个回调以在任务完成后调用

时间:2012-04-24 14:33:44

标签: javascript design-patterns node.js

我似乎找不到这个问题的一般解决方案,即使我觉得我不能成为第一个遇到这个问题的人。我也怀疑这可能是我在这里采取了错误的做法。让我知道。

我有一个Expressjs应用程序与各种API(主要是OAuth2)进行交互。一旦请求进入,应用程序就会检查它是否具有从API获取数据的访问令牌。如果令牌过期,它将请求新的令牌。

现在,当我的应用程序在此期间收到第二个请求时,需要完全相同的API,我想避免再次调用访问令牌。

我所做的是使用“收集器”,可以为给定的密钥存储回调。存储密钥回调的第一个请求获得一个收集器回调,以便在完成任务后调用。所有后续回调都会排队,稍后会使用收集器回调调用。

这是简单的收集器类(CoffeeScript)

# Collect callbacks for tasks and execute all once the job is done
module.exports = class Collector
  constructor: ()->
    @tasks = {}
  add: (key, callback)->
    unless @tasks[key]
      # Initiate callback list for the key with first callback
      @tasks[key] = [callback]
      return ()=>
        # Call all collected callbacks for the key
        (callback.apply {}, arguments for callback in @tasks[key])
        # Reset callback list
        @tasks[key] = null
    else
      # Add callback to existing list
      @tasks[key].push callback
      return false

我不确定在这个类中存储回调是否正确,但是要使用数据库(Redis),我必须找到一种存储回调的方法......

一旦完成作业,是否有更好的方法来调用多个回调?

2 个答案:

答案 0 :(得分:2)

为什么不将回调汇总到一个循环的数组中,在原始调用完成后执行每个包含的函数?

可能很简单:

var dones = [];

dones.push(function (err, res) { console.log('hoo'); });
dones.push(function (err, res) { console.log('ray!'); });

function whenDone(err, res) { 
   _.each(dones, function (done) { done(err, res); } }); 
}

myWhateverFunction(whenDone);

如果你想让它变得更漂亮,你可以把它包装成你想要的任何数据结构。

答案 1 :(得分:0)

我没有针对您的问题的具体答案,但您应该查看异步模块。我认为这是朝着正确方向迈出的一步:https://github.com/caolan/async