简体   繁体   中英

Making an api call inside a loop in node.js

I am trying to scan the top 100 movie torrents on the pirate bay using node and add a movie poster for each result.

I am using these libraries

thepiratebay imdb-api

I am able to find top 100 and return the results with no problems

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

I am also able to look up movies via an IMDB ID and return the results

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

What I am trying to do is loop over the top 100 results pull the imdb id out of the description field out and query imdb replacing the picture field with 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);
     })
 })
});

This isn't working for some reason but it makes sense to me intuitively. If I remove the imdb-api call and replace it with value["picture"] = "foo". It does work. I'm not sure if this is related to how node handles loops. I'm new to the JS world and have a ruby background

Thanks in advance

You are on the right track with the async module but the imdb requests are also asynchronous so res.send just gets called with the initial result of async.map

You can use another async.map for the imdb calls and them chain them with async.waterfall which will pass the results of the first function as an argument to the second ( async.apply just invokes the tpb function with your 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);
        });
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM