2016-02-18 2 views
0

У меня есть метод, который принимает функцию в качестве параметра обратного вызова. Как внешний метод, так и функция обратного вызова возвращают обещания, которые я собираю для массива, ожидая их разрешения с помощью Q.all.Обещание, возвращенное из метода, не определено

function eval() { 
    var colReadPromisses = []; 

    config.mongodb.colls.forEach(function (collName) { 

     var outer = mongo.readCollection(collName, 
       function (jsonData) { 
        var prom = es.pushItemToES(jsonData, esIndexName, collName, i); 
        colReadPromisses.push(prom); 
       }); 
     colReadPromisses.push(outer); 
    }); 

    return Q.all(colReadPromisses); 
} 

Теперь внутренний метод обратного вызова называется много раз, и для их обработки требуется некоторое время. Пока они обрабатываются, обещания, возвращенные из метода readCollection, получают «undefined», вызывающие «Q.all (colReadPromisses)»; Разрешить.

Итак, мои два вопроса были бы связаны с тем, почему nodejs теряет следы на обещания, возвращенные методом 'readCollection', и как мне этого избежать?

Спасибо за ответы!

+0

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

+0

edit done, sorry – greengold

+0

вы говорите 'внутренний обратный вызов метод называется много раз' - это может быть время PER readCollection? –

ответ

1

Я предполагаю, что вы хотите получить результаты всех как readCollection и pushItemToES в возвращенном обещание

function eval() { 

    return Q.all(config.mongodb.colls.map(function (collName) { 

     var pushPromisses = [mongo.readCollection(collName, function (jsonData) { 
      pushPromisses.push(es.pushItemToES(jsonData, esIndexName, collName, i)); 
     })]; 

     return pushPromisses[0] // once the outer promise resolves 
     .then(function() { 
      return Q.all(pushPromisses); // wait for them all (including the outer) 
     }); 

    })); 
} 

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

  • [0][0] будет результатом из mongo.readCollection(colls[0])
  • [0][1..n] будут результаты каждого из pushItemToESreadCollection(colls[0])
  • [1][0] will be the result of the mongo.readCollection (colls [1]) `
  • [1][1..n] будут результаты каждого из pushItemToESreadCollection(colls[1])

и так и на

, если вам не нужен результат mongo.readCollection по возвращенному обещанию

function eval() { 

    return Q.all(config.mongodb.colls.map(function (collName) { 

     var pushPromisses = []; 

     return mongo.readCollection(collName, function (jsonData) { 
      pushPromisses.push(es.pushItemToES(jsonData, esIndexName, collName, i)); 
     }).then(function() { 
      return Q.all(pushPromisses); 
     }); 

    })); 
} 

в этом случае возвращаемый обещание еще два одномерным, но только результаты pushItemToES

  • [0][0..n] будут результаты каждого pushItemToES из readCollection(colls[0])
  • [1][0..n] будут результаты от каждого pushItemToES от readCollection(colls[1])

Я не вижу никакого способа обойти двумерный массив в разрешенном обещании - потому что es.pushItemToES не называется «известным» (по крайней мере, не досрочно) числом

+0

это работает как ожидалось! Мне действительно не нужны никакие результаты от 'pushItemToES'. Я использую обещания только для синхронизации. Кроме того, cau вы скажите, почему я «потерял» ссылку на обещания, полученные от «readCollection», и почему важно использовать «карту» в вашем решении? – greengold

+0

map - это удобство при создании массива чего-то, что 1: 1 из массива чего-то другого. Я только предполагаю, что причина, по которой ваше возвращенное обещание была неправильной, состоит в том, что массив был изменен обратными вызовами после Q. все было вызвано - только спекуляция, хотя ... –

0

Вы должны реорганизовать код:

function eval() { 
    // replace forEach with map 
    var colReadPromisses = config.mongodb.colls.map(function (collName) { 

      // return pushItemToES promises 
      return new Promise(function(resolve) { 
       mongo.readCollection(collName, 
        function (jsonData) { 
         resolve(es.pushItemToES(jsonData, esIndexName, collName, i));     
        }); 
      }); 

    }); 

    // colReadPromisses stores array of pushItemToES promises 
    return Q.all(colReadPromisses); 
} 
+0

если «внутренний метод обратного вызова называется много раз» (я принимаю много раз на каждой итерации внешнего цикла) - ваш код будет разрешен слишком рано (после первого на каждой итерации) –

+0

О, моя вина. Можете ли вы предоставить дополнительную информацию о функции 'readCollection'? Обратный вызов получает только аргумент 'jsonData'? –

Смежные вопросы