如何使用Promises发送一系列请求结果?

时间:2017-09-24 15:36:21

标签: node.js api express promise bluebird

我想设置一个快速服务器,它返回一个项目数组的查询结果。我已在this question中读到我可以使用Promise.each ...

我打算让我的代码做的是:

  • 网页抓取包含电影列表的页面,并将标题作为数组返回。
  • 使用电影标题为每个
  • 请求API
  • 使用每个电影的API响应结果向客户端返回响应

这是我的代码:

var express = require('express');
var app = express();

var Xray = require('x-ray');
var x = Xray();

app.get('/', function (req,res){
    var username = 'medicengonzo';
    var pages = 3;

    x('https://letterboxd.com/'+username+'/watchlist/', 'li.poster-container', [{
            movie: 'img@alt'
            }])(function (err,results){
        console.log('Entered x-ray callback fn');
        results.forEach(function(result, index){
            console.log('Iteration');
            console.log(results.length);
            request('http://netflixroulette.net/api/api.php?title='+encodeURIComponent(result.movie),
                    function(err, response, body){
                        movies = [];
                        console.log(count);
                        obj = JSON.parse(body);
                        if(obj.errorcode != 404){
                            movies.push('Movie found: '+obj.show_title, 'ID: '+obj.show_id);
                        }
                        else{
                            movies.push('No movie found');
                        }
                            res.send(movies);
                    }
            );
        });
    })
    .paginate('.paginate-current+li a@href')
    .limit(pages);
});

app.listen(3000, function(){
    console.log('Listening on port 3000!');
});

1 个答案:

答案 0 :(得分:0)

所以...经过一些谷歌搜索和很多关于Promises和Chaining Promises的学习后,我得到了代码:

var express = require('express');
var app = express();

var Xray = require('x-ray');
var x = Xray();

var Promise  = require('bluebird');
var request = require('request');

var debug = true;

app.get('/', function (req,res){

    if(debug) console.log('Page requested!');

    var username = 'medicengonzo';
    var pages = 3;

    var scrapeMovies = function(){
        if(debug) console.log('scrapeMovies()');
        return new Promise((resolve,reject) => {
            x('https://letterboxd.com/'+username+'/watchlist/', 'li.poster-container', [{
                    title: 'img@alt'
                    }])((err, results) => {
                    console.log('x()');
                if(err) reject(err);
                resolve(results);
            })
            .paginate('.paginate-current+li a@href')
            .limit(pages);

        });
    };

    scrapeMovies().then(
            movies => {
        if(debug) console.log('scrapeMovies() resolved');
        return new Promise.all(movies.map((movie, index) => {
            return new Promise((resolve, reject)=> {
                if(debug) console.log('Requesting: ', movie.title);
                request('http://netflixroulette.net/api/api.php?title='+encodeURIComponent(movie.title), (err, response, body) => {
                        if(debug) console.log('Flixroulette requested');
                        var flixMovie = JSON.parse(body);
                        if(flixMovie.errorcode != 404){
                            resolve('Movie found: '+flixMovie.show_title, 'ID: '+flixMovie.show_id);
                        }
                       else{
                            resolve('No movie found...');
                        }
                });
            });
        }));
    }).then((movies) => res.send(movies)).catch((err) => console.log(err));

});

app.listen(3000, function(){
    console.log('Listening on port 3000!');
});

首先,我定义了一个功能,它将刮掉我需要的电影标题,并返回一个包含所述标题数组的承诺:scrapeMovies()

之后,我将该承诺链接到另一个承诺,该承诺包含将向我发出请求的函数。而不是array.forEach我使用了array.map,而是返回了一个promises数组,每个promise都使用请求中的数据进行解析,最后我res.send()解析数据Promise.all()这是一个包含所有数据的数组。