Шаблоны проектирования JavaScript - работа с нежелательной асинхронностью - PullRequest
15 голосов
/ 13 октября 2010

Я довольно новичок в программировании на основе событий (используя node.js). Я верю, что есть кое-что, чего я просто не замечаю, потому что есть особая проблема, с которой я сталкиваюсь снова и снова и снова.

Короче говоря, эта проблема связана с асинхронностью, когда кажется, что она мешает вам. В моем случае это чаще всего проявляется при работе со сторонними библиотеками, неблокирующими по своему дизайну и продвигающими API на основе обратного вызова.

Например: сейчас я пишу кое-что, что интенсивно использует библиотеку Mranney's node-redis . Моя программа копирует RSS-каналы и помещает результаты в Redis. Я использую то, что считаю общей стратегией с Redis:

  1. Очистить ленту, сохранить результаты в виде хэша Redis с ключом что-то вроде feed:<feedId>:results:<timestamp>.
  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?
}

Поместить return latest_reading внизу функции get_latest_results не удается, поскольку последняя_чтение не определена до после , функция готова к выходу. Размещение return latest_reading в вызове hgetall завершается неудачно, поскольку return относится к обратному вызову и игнорируется get_latest_results.

Это всего лишь один пример ситуации, в которую я, кажется, постоянно пишу. Может быть, я пытаюсь втиснуть квадратный колышек в круглое отверстие, потому что я не знаю ничего лучше. Похоже, должен быть нехакерский способ решения этого класса проблем.

1 Ответ

28 голосов
/ 13 октября 2010

Вы боретесь с асинхронностью, потому что вы все еще пишете свои функции в синхронной парадигме.

В асинхронности вы должны прикреплять обратные вызовы к событиям. Вы не должны ожидать результата от асинхронной функции, такой как 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...
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...