2010-10-12 12 views
15

Sono piuttosto nuovo alla programmazione basata sugli eventi (utilizzando node.js). Credo che ci sia qualcosa che non mi piace, perché c'è un problema particolare che continuo a incontrare ancora e ancora e ancora.Modelli di progettazione JavaScript - Gestione di asincronia indesiderata

In breve, quel problema riguarda l'asincronicità quando sembra che si stia ostacolando. Ciò si manifesta molto spesso, nel mio caso, quando si lavora con librerie di terze parti, che non sono bloccate dalla progettazione e promuovono un'API basata sul callback.

Ad esempio: in questo momento sto scrivendo alcune cose che fanno un uso intenso di mranney's node-redis library. Il mio programma sta raschiando i feed RSS e rimboccando i risultati in redis. Sto usando quella che credo sia una strategia comune con Redis:

  1. alimentazione Raschiare, i risultati negozio come un hash Redis con una chiave di qualcosa come feed:<feedId>:results:<timestamp>.
  2. Riferimento negozio al risultato più recente in 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? 
} 

Posizionamento return latest_reading nella parte inferiore della funzione get_latest_results fallisce, perché latest_reading non è definito fino dopo la funzione è pronta per uscire. L'inserimento di return latest_reading all'interno della chiamata hgetall non riesce perché lo return fa riferimento alla richiamata e viene ignorato da get_latest_results.

Questo è solo un esempio del tipo di situazione in cui mi sembra di scrivere costantemente. Forse sto cercando di colpire il piolo quadrato nel buco rotondo perché non lo so. Sembra che ci dovrebbe essere un modo non hacker di risolvere questa classe di problemi.

risposta

28

Stai lottando con l'asincronia perché stai ancora scrivendo le tue funzioni in un paradigma sincrono.

In asincronia è necessario associare i callback agli eventi. Non dovresti aspettarti un risultato da una funzione asincrona come get_latest_results(), ma dovresti passargli una funzione di callback come argomento da invocare quando i risultati sono pronti. Il callback farà tutto quello che deve essere fatto con i risultati:

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 
} 

quindi è possibile chiamare la funzione in questo modo:

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

+1. Impara a piacergli. 'cos JavaScript non fornisce le primitive a livello di linguaggio come i thread o le coroutine che è necessario essere in grado di eseguire il codice asincrono in modo sincrono (o viceversa). – bobince

Problemi correlati