2010-10-12 34 views
15

我很新的事件编程(使用node.js)。我相信有些事情我只是不喜欢它,因为我遇到了一个特别的问题,我一次又一次地重复着。JavaScript设计模式 - 处理不需要的异步

简而言之,这个问题在处理异步问题的时候似乎正在困扰着你。在我的情况下,这通常表现为与第三方库一起工作,这些库通过设计实现了非阻塞并促进了基于回调的API。

例如:现在我正在写一些东西,使大量使用mranney's node-redis library。我的程序正在抓取RSS源,并将结果放入redis中。我正在使用我认为是使用redis的常见策略:

  1. 刮掉feed,将结果存储为带有类似feed:<feedId>:results:<timestamp>之类的键的redis哈希值。
  2. 商店参考feed:<feedId>:latest下的最新结果。
 
var redis = require("redis"); 
var client = redis.createClient(); 

var get_latest_results = function (feedId) { 
    client.get('feed:+ feedId + ':latest', function (err, res) { 
     var latest_reading_key = res.toString(); 
     client.hgetall(latest_reading_key, function (err, res) { 
      var latest_reading = res; 
     }); 
    }); 
    // how do I specify a return value for this function? 
} 

get_latest_results函数失败的底部放置return latest_reading,因为latest_reading不是直到后的功能是准备退出定义。拨return latest_readinghgetall呼叫失败,因为return引用回调,并被get_latest_results忽略。

这只是我似乎不断写入自己的方式的一种情况。也许我正在试图把这个方形钉子打入圆洞,因为我不知道更好。似乎应该有一种解决这类问题的非破解方式。

回答

28

由于您仍在使用同步范例编写函数,因此您正在使用异步方式挣扎。

在异步中,您应该将回调附加到事件。你不应该期望像get_latest_results()这样的异步函数产生的结果,但是你应该把它作为一个参数传递给回调函数,以便在结果准备就绪时调用它。回调将做任何需要对你的成绩来完成:

var get_latest_results = function (feedId, readyCallback) { 
    client.get('feed:' + feedId + ':latest', function (err, res) { 
     var latest_reading_key = res.toString(); 
     client.hgetall(latest_reading_key, function (err, res) { 
      readyCallback(res);       //--- Trigger Callback 
     }); 
    }); 
    // how do I specify a return value for this function? //--- You don't 
} 

然后,你可以调用你的函数是这样的:

get_latest_results(1000, function (result) { 
    //--- Do whatever needs to be done with the latest result... 
}); 
+4

+1。学会喜欢它。 'cos JavaScript不会为您提供像线程或协程那样的语言级原语,您需要能够同步运行异步代码(反之亦然)。 – bobince 2010-10-12 21:27:28