Выполнение вызова api внутри цикла в node.js

#javascript #node.js #api #loops

#javascript #node.js #API #циклы

Вопрос:

Я пытаюсь отсканировать 100 лучших торрентов фильмов в the pirate Bay с помощью node и добавить постер фильма для каждого результата.

Я использую эти библиотеки

thepiratebay
imdb-api

Я могу найти top 100 и вернуть результаты без проблем

 app.get('/movies', function(req, res){
 tpb.topTorrents(207).then(function(topMovies){
    async.map(topMovies, tpb.getTorrent, function(err, results){
        res.send(results);
    })
 })
});
  

Я также могу просматривать фильмы по идентификатору IMDB и возвращать результаты

 app.get('/imdb', function(req, res){
 imdb.getReq({ id: 'tt2660888' }, function(err, things) {
    res.send(things);
 });
});
  

Что я пытаюсь сделать, так это перебрать 100 лучших результатов, извлечь imdb id из поля description и запросить imdb, заменив поле picture на result.

 app.get('/movies', function(req, res){
 tpb.topTorrents(207).then(function(topMovies){
     async.map(topMovies, tpb.getTorrent, function(err, results){
         for (var value of results) {
             if (S(value.description).contains('www.imdb.com/title/')) {
                 var imdbId = S(value.description).between('www.imdb.com/title/', '/').s
                     imdb.getReq({ id: imdbId }, function(err, movie) {
                         value["picture"] = movie.poster
                     });
             }
         }
         res.send(results);
     })
 })
});
  

По какой-то причине это не работает, но для меня интуитивно это имеет смысл. Если я удалю вызов imdb-api и заменю его значением [«picture»] = «foo». Это действительно работает. Я не уверен, связано ли это с тем, как узел обрабатывает циклы. Я новичок в мире JS и имею опыт работы с ruby

Заранее спасибо

Комментарии:

1. Пиратская бухта закрыта, так что почистить ее прямо сейчас, вероятно, не получится.

2. Нет, это не так. В любом случае, моя проблема не в tpb

3. Неясно, что представляют собой все эти функции, даже не ясно, что такое async , но я предполагаю, что это обычное асинхронное промежуточное программное обеспечение. В любом случае imdb.getReq() выполняется асинхронно, и вы, вероятно, получаете изображения, но res.send() это происходит задолго до этого, вероятно, даже до того, как вы получите первый ответ из IMDB и замените первое изображение.

4. Ваш цикл for не является вызовом синхронизации, как написано. Таким образом, res.send достигается до того, как вы фактически измените значение.

Ответ №1:

Вы на правильном пути с асинхронным модулем, но запросы imdb также асинхронны, поэтому res.send просто вызывается с начальным результатом async.map

Вы можете использовать другой async.map для вызовов imdb и связать их с ними по цепочке, async.waterfall который передаст результаты первой функции в качестве аргумента второй ( async.apply просто вызывает функцию tpb с вашим topMovies ).

 function tpb (topMovies, done) {
    async.map(topMovies, tpb.getTorrent, done);
}

function imdb (movies, done) {
    function lookup (value, callback) {
        if (S(value.description).contains('www.imdb.com/title/')) {
            var imdbId = S(value.description).between('www.imdb.com/title/', '/').s
            imdb.getReq({ id: imdbId }, function(err, movie) {
                value["picture"] = movie.poster
                return cb(err, value);
            });
        } else {
            return callback(null);
        }
    }

    async.map(movies, lookup, done);
}

app.get('/movies', function(req, res){
    tpb.topTorrents(207).then(function(topMovies){
        async.waterfall([async.apply(tpb, topMovies), imdb], function (err, results) {
            if (err) {
                // do error handling
            }
            return res.send(results);
        });
    });
});
  

Комментарии:

1. Спасибо, ценю помощь, но у меня это не работает. Я не получаю от него ответа