2014-09-15 2 views
0

Я пытаюсь решить проблему, с которой я столкнулся с узлом knzjs. Таким образом, в основном, этот запрос захватывает мои треки из soundcloud, я просматриваю результаты и помещаю данные в коллекцию mongodb. Все это отлично работает, но теперь я добавляю еще один раздел на сайт, поэтому мне нужно получить дополнительную информацию из другой коллекции.Проблемы с многочисленными обратными вызовами Node.js

У меня есть коллекция треков и коллекция инвентаря. Идентификатор трека находится в обеих коллекциях, чтобы связать дополнительные данные трека с вновь вытащенными дорожками. Итак, мой вопрос в том, как я могу получить эти дополнительные данные трека? Ниже я попытался пропустить его и ввести данные с помощью запроса query.find(), но петли не работают вместе. Обратный вызов запроса инвентаря будет запускаться все в одном для цикла, кажется ... Я не совсем уверен, что происходит там.

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

Если у кого-то есть предложения для меня, это было бы здорово!

request({ 
url: url, 
json: true 
}, function (error, response, body) { 
if (!error && response.statusCode === 200) { 
     var o = 1; 

     for(i=0; i < body.tracks.length; i++){ 
      var last = (i + 1); 
      var track = body.tracks[i]; 

      if(track.sharing == 'public'){ 
       var invData; 
       var obj; 

       db.model('inventory').find({id:track.id}).exec(function(err,item){ 
        //console.log(item[0]); 
        invData = item[0]; 


       }); 


       console.log(invData, obj); 

       obj = new TracksModel({ 
        id: track.id, 
        sharing:track.sharing, 
        uri:track.uri, 
        description:track.description, 
        created_at:track.created_at, 
        duration:track.duration, 
        title:track.title, 
        description:track.description, 
        order: o, 
        inventory_data: invData 
       }); 





       o++; 

       obj.save(function (err) { 
        if (!err) { 
         console.log('Track inserted successfully'); 
        } else { 
         throw err; 
        } 
       }); 

       if(last == body.length){ 
        setTimeout(function(){ 
         console.log("Automatically closing database connection after 5 seconds"); 
         db.close(); 
        }, 5000); 
       } 

      } 

     } 

} else { 
    console.log('An error has occurred: ', error); 
} 
}); 

ответ

1

То, как вы обрабатываете обратный вызов запроса, неверно. Вы предполагаете, что код, начинающийся с «console.log (invData, obj);» будет выполняться сразу после db.model.find. Это не правильное понятие обратного вызова. Как включить этот код внутри функции обратного вызова exec. Возможно, вам придется использовать закрытие. Что-то вроде:

if (!error && response.statusCode === 200) { 
    var o = 1; 

    for(i=0; i < body.tracks.length; i++){ 
     var last = (i + 1); 
     var track = body.tracks[i]; 

     if(track.sharing == 'public'){ 

      (function(track,last,o){ 

       var invData; 
       var obj; 

       db.model('inventory').find({id:track.id}).exec(function(err,item){ 
        //console.log(item[0]); 
        invData = item[0]; 

        console.log(invData, obj); 

        obj = new TracksModel({ 
         id: track.id, 
         sharing:track.sharing, 
         uri:track.uri, 
         description:track.description, 
         created_at:track.created_at, 
         duration:track.duration, 
         title:track.title, 
         description:track.description, 
         order: o, 
         inventory_data: invData 
        }); 

        obj.save(function (err) { 
         if (!err) { 
          console.log('Track inserted successfully'); 
         } else { 
          throw err; 
         } 
        }); 

        if(last == body.length){ 
         setTimeout(function(){ 
          console.log("Automatically closing database connection after 5 seconds"); 
          db.close(); 
         }, 5000); 
        } 
       }); 
      }(track,last,o);  

      o++; 
     } 

    } 

}

+0

Так что цель '(функции (дорожки, наконец, о) {} (трек, наконец, о); '? Если я правильно понимаю exec, он сразу же выполняет обратный вызов в том же цикле цикла' for'? Спасибо за ваш ответ! –

+0

Команда find является асинхронной, и поэтому exec не будет выполняться сразу. exec - это функция обратного вызова find и будет вызываться только тогда, когда find прекращается. В вашем коде, весь код, который находится после поиска, называется сразу. (Function (track, last, o) {} (track, last, o) - это доступ к правильным значениям внутри функции exec. Если вы хотите, я могу лучше объяснить, почему использование этой функции с примером. –

+0

реализовал ваш код, и он отлично поработал! Вам просто не хватает закрывающей скобки после анонной функции '} (track, last, o));'. Спасибо за вашу помощь! –

0

Попробуйте это:

var utils = require('restberry-utils'); 

var Inventory = mongoose.model('Inventory'); 
var Track = mongoose.model('Track'); 

request({ 
    url: url, 
    json: true 
}, function (error, response, body) { 
    if (error || response.statusCode !== 200) { 
     console.log('An error has occurred: ', error); 
     return; 
    } 
    utils.forEachAndDone(body.track, function(track, iter) { 
     if (track.sharing !== 'public') { 
      iter(); 
      return; 
     } 
     Inventory.findOne({ id: track.id }, function(err, item) { 
      new Track({ 
       id: track.id, 
       sharing: track.sharing, 
       uri: track.uri, 
       description: track.description, 
       created_at: track.created_at, 
       duration: track.duration, 
       title: track.title, 
       description: track.description, 
       order: o, 
       inventory_data: item, 
      }).save(function(err) { 
       if (err) { 
        throw err; 
       } else { 
        console.log('Track inserted successfully'); 
        iter(); 
       } 
      }) 
     }); 
    }, function() { 
     console.log('Done!'); 
     setTimeout(function() { 
      console.log("Automatically closing database connection after 5 seconds"); 
      db.close(); 
     }, 5000); 
    }) 
}); 
+0

Интересно! Вы находите, что функции бонуса действительно полезны? Мне нравится держать вещи светлыми, но если это облегчит мою жизнь, у меня нет проблем с этим. Спасибо за ответ! Все еще пытаюсь обернуть голову вокруг письменного узла, как это. –

+0

Я автор похлебки, поэтому я думаю, что это полезно;) метод forEachAndDone хорош для того, когда вам нужно пройти через массив, а затем выполнить некоторую операцию в конце, что всегда сложно с обратными вызовами. Это не очень сложный способ реализовать себя, чтобы вы могли это сделать, не хотели делать это для этого ответа, почему я предпочитаю импортировать utils, который я использую много :) –

+0

oh cool, да получение обратных вызовов происходит правильно мне сложно в узле. Я проверю это! Благодаря! –

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