【问题标题】:Multiple API calls inside loop循环内的多个 API 调用
【发布时间】:2018-02-13 18:47:45
【问题描述】:

循环内的多个 API 调用 我在循环中进行了多个 API 调用,函数在一个 Promise 中被调用并将数据传递给 body 这部分工作正常,在一个函数中返回一个对 API 进行多次调用的 Promise,在继续之前我必须得到所有结果。但是当我控制台记录结果时,它显示空数组。

    var rp = require('request-promise');
    var watchonlinemovie = []; 


 exports.db = function(body){

    return new Promise((resolve,reject)=>{




        if(body.lenght > 0)
        { 
            body.forEach(movie)
            { 
                let title = movie.title;
                title = (title.slice(0,title.indexOf('('))).trim();
                let year = movie.title; 
                year = year.slice(year.indexOf('(')+1,year.indexOf(')'));

                let call = "http://www.omdbapi.com/?t="+title+"&y="+year+"&apikey="+key2+"&plot=full";

         rp(call)
          .then((body) => {


                   let movie = JSON.parse(body);

                   watchonlinemovie.push({
                     title: movie.Title, 
                     year:movie.Year, 
                     rating:movie.Rated,
                     duration:movie.Runtime,
                     genre:movie.Genre,
                     director:movie.Director, 
                     actors:movie.Actors,
                     image:movie.Poster,
                     href:movie.link, 
                   });     
         })
         .catch(err => { 
           reject(err);
         });
            }
        }

        resolve(watchonlinemovie);
    });
}

【问题讨论】:

  • 使用 Promise.all([]) 使所有请求并行,所有请求完成后返回结果。
  • 您在body.length 中有错字。
  • 对不起,我看到错字还有其他错字,我正在删除它们,感谢您突出显示它。我是 javascript 和 nodejs 的新手

标签: javascript node.js


【解决方案1】:

您可以使用 async.eachOfLimit 来处理所有行。您可以将限制调整为 1 x 1 或 5 x 5 或全部并行(如果有千行,请不要这样做)。

以 10 x 10 为例。

    var async = require("async");
    var rp = require('request-promise');


     exports.db = function(body){

        return new Promise((resolve,reject)=>{

            var watchonlinemovie = []; 

            // change the limit here
            // process all request with a batch of 10
            async.eachOfLimit(body, 10, function(movie, i, ecb){

                // function called for each line in body

                let title = movie.title;
                title = (title.slice(0,title.indexOf('('))).trim();
                let year = movie.title; 
                year = year.slice(year.indexOf('(')+1,year.indexOf(')'));

                let call = "http://www.omdbapi.com/?t="+title+"&y="+year+"&apikey="+key2+"&plot=full";

                rp(call)
                .then((body) => {


                   let movie = JSON.parse(body);

                   watchonlinemovie.push({
                     title: movie.Title, 
                     year:movie.Year, 
                     rating:movie.Rated,
                     duration:movie.Runtime,
                     genre:movie.Genre,
                     director:movie.Director, 
                     actors:movie.Actors,
                     image:movie.Poster,
                     href:movie.link, 
                   });

                   // proceed next movie
                   return ecb(null); 
                })
                .catch(err => { 

                    // stop the async process
                    return ecb(err);
                 });
             })

            }, function(err){

                // final callback, when all request in the body has been proceed
                if(err)
                {
                     reject(err);
                }
                else
                {
                    resolve(watchonlinemovie); 
                }
            });

        });
    }

【讨论】:

    【解决方案2】:

    这是一个使用 Promise 的解决方案,我添加了一些内容,不允许 Promise 拒绝,而是创建一个 Fail 类型值,您可以从结果中选择它们。

    如果您需要限制,可以从here 导入文件。

    var rp = require('request-promise');
    
    const movieToUrl = key2 => movie => {
      const title = movie.title.slice(0, title.indexOf('(')).trim();
      const year = movie.title.slice(title.indexOf('(') + 1, title.indexOf(')'));
      let call = "http://www.omdbapi.com/?t=" + title + "&y=" + year + 
        "&apikey=" + key2 + "&plot=full";
    };
    
    const movieDataToMovieInstance = movie => ({
      title: movie.Title,
      year: movie.Year,
      rating: movie.Rated,
      duration: movie.Runtime,
      genre: movie.Genre,
      director: movie.Director,
      actors: movie.Actors,
      image: movie.Poster,
      href: movie.link,
    });
    
    const Fail = function(reason){this.reason=reason;};
    const isFail = x=>(x&&x.constructor)===Fail;
    const isNotFail = x=>!isFail(x);
    
    //if you want to throttle promises like max5 active or max5 per second
    //  you can use throttle library here:
    //  https://github.com/amsterdamharu/lib/blob/master/src/index.js
    //const max5=lib.throttle(5);//this is max 5 active connections
    //const max5=throttlePeriod(5,1000);//this is max 5 per second
    
    
    exports.db = function (body) {
      return Promise.all(
        body.map(
          movieToUrl(key2)//key2 comes out of nowhere
          //throttled version
          //.then(max5(rp))
          .then(rp)
          .then(movieDataToMovieInstance)
          .catch(err=>new Fail([body,err]))
        )
      );
    };
    
    //example how to use:
    exports.db(someBody)
    .then(
      results=>{
        const successes = results.filter(isNotFail);
        const failures = results.filter(isFail);
      }
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2019-03-24
      • 2021-01-29
      • 2020-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多