2010-10-12 15 views
15

Jestem całkiem nowy w programowaniu opartym na zdarzeniach (przy użyciu pliku node.js). Sądzę, że jest coś, o czym po prostu się nie dowiaduję, ponieważ jest pewien szczególny problem, z którym ciągle się spotykam.Wzorce projektowe JavaScript - rozwiązywanie problemów z niechcianą asynchronią

Krótko mówiąc, problem ten polega na asynchroniczności, gdy wydaje się, że przeszkadza. Najczęściej objawia się to w moim przypadku podczas pracy z bibliotekami firm trzecich, które nie blokują projektu i nie promują interfejsu API opartego na oddzwanianiu.

Na przykład: W tej chwili piszę niektóre rzeczy, które intensywnie korzystają z mranney's node-redis library. Mój program zbiera dane RSS i umieszcza wyniki w Redis. Używam co wierzę jest wspólna strategia z REDiS:

  1. Zeskrobać feed przechowywać wyniki jako hash Redis z kluczem czegoś podobnego feed:<feedId>:results:<timestamp>.
  2. Zapisz referencję do najnowszego wyniku pod numerem 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? 
} 

Umieszczenie return latest_reading na dole funkcji get_latest_results zawodzi, ponieważ latest_reading nie jest zdefiniowana aż po funkcja jest gotowy, aby wyjść. Umieszczanie return latest_reading w ramach połączenia hgetall kończy się niepowodzeniem, ponieważ return odnosi się do wywołania zwrotnego i jest ignorowane przez get_latest_results.

To tylko jeden z przykładów sytuacji, w której ciągle się zapisuję. Może próbuję wbić kwadratowy kołek w okrągłą dziurę, bo nie wiem nic lepszego. Wydaje się, że powinien istnieć nie-hackowy sposób rozwiązywania tej klasy problemów.

Odpowiedz

28

Walczysz z asynchronią, ponieważ wciąż piszesz swoje funkcje w paradygmacie synchronicznym.

W asynchronii należy dołączać wywołania zwrotne do zdarzeń. Nie powinieneś oczekiwać rezultatu z funkcji asynchronicznej, takiej jak get_latest_results(), ale powinieneś przekazać jej funkcję wywołania zwrotnego jako argument do wywołania, gdy wyniki są gotowe. Callback zrobi co należy zrobić z wynikami:

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 
} 

Następnie można wywołać czynność tak:

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

+1. Naucz się go polubić. "cos JavaScript nie daje ci prymitywów na poziomie języka, takich jak wątki lub programy typu coroutines, które są potrzebne do synchronicznego uruchamiania kodu asynchronicznego (lub odwrotnie). – bobince

Powiązane problemy