Как получить два параметра двух асинхронных функций? - PullRequest
1 голос
/ 11 октября 2011
var o = new X();
o.setFooCallback1(function(result1){
});
o.setFooCallback2(function(result2){
});
o.foo("xxx");  

Как вы можете видеть, когда я звоню o.foo(), вы получите два обратных вызова с двумя результатами: result1 и result2, и я хочу использовать pass result1 иresult2 в мою конструкторскую функцию для создания объекта:

var y = new Y(result1, result2);  

Но result1 и result2 приходят в разное время (асинхронно) could как я могу справиться с этим?из чужой библиотеки я не могу изменить ее реализацию

Ответы [ 3 ]

3 голосов
/ 11 октября 2011

Вам необходимо реализовать так называемый шаблон семафора

Вот практическая реализация:

var o = new X()
  , n = 0
  , result1, result2

function checkResults(){
    if (--n > 0) return;
    var y = new Y(result1, result2)
}

o.setFooCallback1(function(res){
    result1 = res
    checkResults()
})

o.setFooCallback2(function(res){
    result2 = res
    checkResults()
})

Или объектно-ориентированный подход:

function Semaphore(callback){
    this.callback = callback
    this.count = 0
    this.args = []
}
Semaphore.prototype.check = function(){
    if (--this.count <= 0)
        this.callback.apply(null, this.args)
}
Semaphore.prototype.queue = function(){
    var self = this
    self.count++
    return function(res){
        self.args.push(res)
        self.check()
    }
}

var fooResults = new Semaphore(function(res1, res2){
    var y = new Y(res1, res2)
})

o.setFooCallback1(fooResults.queue())
o.setFooCallback2(fooResults.queue())

Обратите внимание, что он захватывает только первые аргументы обратного вызова, но вы можете легко расширить его на все, что вам нужно.

1 голос
/ 11 октября 2011

В основном вам нужно добавить еще один слой, который запускает обратный вызов после выполнения обоих обратных вызовов с первого уровня, возможно, в другом объекте.Ответ здесь довольно хороший:

Обратный вызов jQuery для нескольких вызовов ajax

0 голосов
/ 11 октября 2011

Вызовите одну и ту же функцию из обоих обратных вызовов, но на самом деле сделайте что-нибудь только после того, как они оба вернутся, например:

(function(){
  var y, r1, r2;

  function runWhenBothReturn() {
    if(r1 && r2) { //check both are set to a non-falsy value
      y = new Y(r1, r2); 
    }
  }

  var o = new X();

  o.setFooCallback1(function(result1){
    r1 = result1;
    runWhenBothReturn();
  });

  o.setFooCallback2(function(result2){
    r2 = result21;
    runWhenBothReturn();
  });

  o.foo("xxx"); 

})();

Обратите внимание, что я добавил замыкание, чтобы y, r1 и r2 не становятся глобальными переменными, но остаются локальными для задачи.

Если либо r1, либо r2 могут иметь значения, которые оцениваются как ложные, то обязательно обновите ifпредложение соответственно:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...