2015-01-03 2 views
1

Я не могу найти способ заставить мою функцию поиска работать. Я хотел бы найти все billIds из коллекции счетов, а затем проверить каждый billId внутри транзакции DB.Mongoose find() проблемы с обратными вызовами

Проблема в том, что из-за aSynch - я считаю, что идентификатор не обновляется в моем цикле. Вот код:

Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){ 
     if(err) 
      res.send(err); 

     details.bills = bills; 

     for(key in bills){ 
      var billId = bills[key]._id; 
      console.log("BillId: " + billId); // Here the ids are unique (which is what I want) 

      Transactions.find({billId : billId}, function(err, transactions){ 
       if (err) { 
        console.log('error: '+ err) 
       } else { 
        console.log("Transaction BillId: " + billId); // Here I get always the same ID - which is not quiet what I need. 
       } 
      }); 


      //console.log(transactions); 
     } 

     res.send(details); 
    }); 

Там результат на консоли:

BillId: 549bf0597886c3763e000001 
BillId: 54a014bfac01ca3526000001 
BillId: 54a015753547a6c026000001 

^Хороший результат - Поставляется с первого console.log внутри для().

, а затем:

Transaction BillId: 54a015753547a6c026000001 
Transaction BillId: 54a015753547a6c026000001 
Transaction BillId: 54a015753547a6c026000001 

^Плохой результат - Его повторив результат последнего из за() и мне нужны все результаты.

На первой консоли.log(), когда я получаю результаты от первого find() (Bills.find()), я могу видеть все идентификаторы в журнале, но когда я пытаюсь получить их во втором Find (Transactions.find())), они повторяют последний идентификатор. Так что в этом текущем состоянии я не могу запросить db для каждого id. Любая помощь по этому поводу ценится.

Пожалуйста, дайте мне знать, если вам нужно какое-либо разъяснение.

Заранее благодарен!

+0

'вар billId = счетов [Элемент] ._ идентификатор;' должен быть 'вар billId = item._id'. – BatScream

+0

Это не главное. Я получаю billId там, проблема в том, что когда я пытаюсь выполнить 'Transactions.Find()' на каждый billId, billId всегда является последним billId из 'Bills.find()'. Кроме того, ваше предложение не будет работать, поскольку элемент представляет ключ в моем массиве. –

ответ

0

Классическая ошибка функции закрытия внутри цикла.

Ваше значение переменной меняет каждый шаг шага. С другой стороны, ваша функция будет выполнена позже (через некоторое время), когда переменная уже много раз менялась.

Посмотрите на ссылки разъяснений:

Creating closures in loops: A common mistake

JavaScript closure inside loops – simple practical example

Javascript infamous Loop issue?

0

Если ваша функция Transactions.find асинхронна, ее обратный вызов выполняется в более поздний момент времени, после завершения цикла for ... in. В то время billId имеет значение, которое оно было присвоено при последнем запуске цикла for ... in. Поэтому все прогоны обратного вызова распечатывают это значение.

Если вы хотите провести на ценности, вы должны создать closure где-то, как это:

(function (id) { 
    Transactions.find(..., function (...) { 
     // ... use `id` here 
    }); 
})(billId); 

Если bills является Array или если вы используете некоторые утилиты библиотеке, например Lo-Dash, вы можете использовать функцию итерации, например Array.prototype.map или lodash.each, которая использует закрытие, так что вам не нужно будет создавать ее отдельно.

0

Отлично!

Спасибо за советы ребятам. Я решил это, используя Underscore each function.

Вот как: Вместо того, чтобы цикл с for, я простой заменил для по _.each, как в примере ниже:

Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){ 
    if(err) 
     res.send(err); 

    details.bills = bills; 

    _.each(bills, function(item){   
     var billId = item._id; 
     console.log("BillId: " + billId); 

     Transactions.find({billId : billId}, function(err, transactions){ 
      if (err) { 
       console.log('error: '+ err) 
      } else { 
       console.log("Transaction BillId: " + billId); 
      } 
     }); 


     //console.log(transactions); 
    }); 

    res.send(details); 
}); 
+0

Если ответ решил вашу проблему, лучше пометить его как _приобретенный_, чем переписать весь код с небольшим изменением в отдельном ответе. – hon2a

+0

Спасибо! Но мне действительно нравится публиковать именно то, что решает проблему, поскольку я считаю, что не все здесь такие эксперты, как вы, ребята, и предложение не всегда разъясняет, что именно вам нужно сделать, чтобы решить вашу проблему. Поэтому публикация решения «точка-точка» поможет другим любителям, таким как я. –

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