在数百个承诺之间添加延迟或其他内容

时间:2017-07-04 09:11:40

标签: javascript node.js

我使用节点从其他网站请求应用详细信息,但我面临的问题是,它发送了数百(或几千)个请求,然后我收到错误,我什么都没收到。< / p>

阅读代码中的评论信息......

// I'm reading links from another file using 'fs'
fs.readFile('./google_apps/GAME_ACTION.json', 'utf8', function (err, data) {
    if (err) throw err;

    obj = JSON.parse(data);
    // creating a empty array
    var promiseStack = [];

    for (var index in obj['GAME_ACTION']) {
        var linksArray = obj['GAME_ACTION'][index];
        linksArray.forEach( function(link, index) {
            var appID = link.match(/id=.*/g)
            var instr = appID.toString();

            var appIDSliced = instr.slice(3)
            // Here appIDSliced is ID, which is sliced from a link
            // there are thousands on link in this file which I opened

            console.log('sending') // for testing purpose

            // here i'm pushing promises into that empty array
            // store.app({id: appIDSliced}) is a promise I guess because I can use .then() on it...
            // and store.app sends request to another website from which it receives an object in return. 
            // (Variable store is from another file 'require()' above in my node app fie )
            promiseStack.push( store.app({id: appIDSliced}))

        });
    }


    // After pushing all promises into array, now i'm trying to resolve them using Promise.all
    Promise.all(promiseStack).then((responses) => {
        console.log("Dealing with responses")

        // Dealing with response (which is an object coming)
        responses.map(response => {
            var title = response.title
            var package_name = response.appId
            var appCategory = response.primaryGenre
            var appSize = parseFloat((response.size/1024)/1024).toFixed(2)
            var developerName = response.developer
            var developerWebsite = response.developerWebsite
            if (typeof developerWebsite == 'undefined') {
                developerWebsite = "N/A"
            }
            var appPrice = response.price
            var lastUpdated = response.updated
            var contentRating = response.contentRating
            if (typeof contentRating == 'undefined') {
                contentRating = "N/A"
            }
            var userRating = response.score
            if (typeof userRating == 'undefined') {
                userRating = "N/A"
            }
            var dataRow = [appID, title, package_name, appCategory, appSize, developerName, developerWebsite, appPrice, lastUpdated, contentRating, userRating]
            var dataToAdd = [dataRow];
            console.log("Appending now")

            // here i'm using google API to append that into my sheet on google
            authentication.authenticate().then((auth)=>{
                appendData(auth, dataToAdd);
            });
        })
    })
})

请参见下图...这些是我在控制台上收到的错误 它不断记录和发送&#39;喜欢80秒,然后我得到错误&#34; UnhandledPromiseRejectionWarning&#34;在那里我被卡住了2分钟而且我一直按着“CTRL + C&#39;”。 Error I receive on my console

感谢。

4 个答案:

答案 0 :(得分:1)

在您的情况下,

async.each可能更合适,请查看async.each

Promise.all()在这种情况下看起来并不正确,因为方法返回一个Promise,它在iterable参数中的所有promise都已解析或者iterable参数不包含promise时解析。它拒绝承认拒绝的第一个承诺。 promise.all

我试图用异步重写你的代码,我做的假设很少,这是你可能会根据逻辑调整它的一般例子。

var async = require('async');
fs.readFile('./google_apps/GAME_ACTION.json', 'utf8', function (err, data) {
    if (err) throw err;

    var obj = JSON.parse(data);
    async.each(obj['GAME_ACTION'], function(linksArray, callback){
        linksArray.forEach( function(link,) {
            var appID = link.match(/id=.*/g);
            var instr = appID.toString();

            var appIDSliced = instr.slice(3);

            console.log('sending') // for testing purpose
            // I am assuming that store.app() is asyncronous and get a callback
            store.app({id: appIDSliced}, function(err, response){
                if (err){
                    console.log('something bad happend');
                    callback();
                }
                else{
                        var title = response.title;
                        var package_name = response.appId;
                        var appCategory = response.primaryGenre;
                        var appSize = parseFloat((response.size/1024)/1024).toFixed(2);
                        var developerName = response.developer;
                        var developerWebsite = response.developerWebsite;
                        if (typeof developerWebsite == 'undefined') {
                            developerWebsite = "N/A"
                        }
                        var appPrice = response.price;
                        var lastUpdated = response.updated;
                        var contentRating = response.contentRating;
                        if (typeof contentRating == 'undefined') {
                            contentRating = "N/A"
                        }
                        var userRating = response.score;
                        if (typeof userRating == 'undefined') {
                            userRating = "N/A"
                        }
                        var dataRow = [appID, title, package_name, appCategory, appSize, developerName, developerWebsite, appPrice, lastUpdated, contentRating, userRating]
                        var dataToAdd = [dataRow];
                        console.log("Appending now");

                        authentication.authenticate().then((auth)=>{
                            appendData(auth, dataToAdd);
                        });
                    callback();
                }
            });
        });
    }, function (err) {

    });

});

答案 1 :(得分:0)

您可以使用伪递归方法慢慢迭代一个又一个请求:

CREATE TABLE #SampleData
(
    Name varchar(10),
    Location varchar(20),
    Item varchar(10),
    Date varchar(8)
)
INSERT INTO #SampleData
VALUES
('Ron', 'Loc A', 'Pencil', '20170610'),
('Ron', 'Loc A', 'Pencil', '20170611'),
('Ron', 'Loc B', 'Pen', '20170610'),
('Ron', 'Loc B', 'Laptop', '20170611'),
('Tom', 'Loc A', 'Pencil', '20170611'),
('Tom', 'Loc B', 'Pencil', '20170610'),
('Tom', 'Loc B', 'Pen', '20170610'),
('Tom', 'Loc A', 'Pencil', '20170610'),
('Tom', 'Loc A', 'Laptop', '20170610'),
('Tom', 'Loc A', 'Pencil', '20170610')

    DECLARE @Pivot_Columns  AS VARCHAR(MAX),
            @select_Columns VARCHAR(max)

    SELECT @Pivot_Columns = Stuff((SELECT DISTINCT ',' + Quotename(Item) FROM #SampleData FOR xml path('')), 1, 1, '')
    SELECT @select_Columns = Stuff((SELECT DISTINCT ',Sum(' + Quotename(Item) + ') as '+Quotename(Item) FROM #SampleData FOR xml path('')), 1, 1, '')

    DECLARE @SQL AS VARCHAR(MAX)

    SET @SQL = 'SELECT case when grouping(location) = 1 and grouping(name) = 0 then ''Total''+ '' '' + name 
    when grouping(location) = 1 and grouping(name) = 1 then ''Total'' 
    else name end Name, 
    case when grouping(location) = 1 and grouping(name) = 0 then CONVERT(varchar(10), COUNT(Distinct location ))
    when grouping(location) = 1 and grouping(name) = 1 then CONVERT(varchar(10), COUNT(Distinct location ))
    else Location end Location,
    '+ @select_Columns + '
    FROM
    (
        SELECT name, location, item
        FROM #SampleData

    ) as PivotData
    PIVOT
    (
        count(item)
        for item  IN ('
               + @Pivot_Columns + ')
    ) AS PivotResult
    group by name,location with rollup 
    '

    EXEC(@SQL) 

答案 2 :(得分:0)

for loop当您推动store.app({id: appIDSliced})&amp;我猜它开始以突发模式请求服务器。 Promise.all正在解决陷入困境的请求。

为什么不运行n numbers at a time并让它们关注直到所有服务器请求都完成。这样,大多数请求之间都会有延迟,因为在任何时候都会有最多5个请求运行而不是突发执行。

&#13;
&#13;
var functions = [];
var m;
for (var i = 0; i < 100; i++) {
  (function(j) {
    functions.push(function(callback) {
      var random = Math.floor(Math.random() * 10000) + 1;
      var s = document.getElementById('here');
      var d = document.createElement('div');
      d.innerHTML = 'function : ' + j + ' executed after :' + random;
      s.appendChild(d);
      setTimeout(callback, random);
      // the above code executes something like xhr. remove it
      // here you can write your own statements
      // store.app({id: appIDSliced}, (err, response) => {
      //     responses.map(response => {
      //         var title = response.title
      //         {...}
      //         here i'm using google API to append that into my sheet on google
      //         authentication.authenticate().then((auth)=>{
      //            appendData(auth, dataToAdd);
      //         });
      //     });
      //     callback(); // you can add callback here after all your statements execution
      // });
    });
  })(i);
}

function exec(method) {
  // here method will call the below function which is in your case promise.
  // function(callback) {
  //     console.log(j);
  //     callback();
  // }
  method(function() {
    if (functions.length > m) {
      exec(functions[m]);
      m++;
    }
  });
}

// lets start only 5 at a time.
// first to complete next to start
// function number:    1      2     3     4     5
// completes :        2nd    3rd   1st   5th   4th
// start new :         7      8     6     10    9
setTimeout(function() {
  for (m = 0; m < 5; m++) {
    (function(m) {
      exec(functions[m]); // this will execute 1,2,3,4,5 function
      m++;
    })(m);
  }
}, 0);
&#13;
<div id="here"></div>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

var Promise = require('bluebird');

function fetchData(objekt){
  return new Promise((resolve, reject) => {
      // api call and then 
      resolve(data);
  })
}

function doRequest(){

 Promise.coroutine(function *(){
        yield Promise.map(arr, fetchData);
 })()
 .catch(err => {
    console.error(err);
  })
}

一个简单而短的代码,带有错误处理。