2010-10-12 35 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