2017-07-04 50 views
0

我正在使用節點從另一個網站請求應用程序詳細信息,但是我面臨的問題是它發送了數百(或者數千)的請求,然後出現錯誤,而我一無所獲。在幾百個承諾之間添加延遲

閱讀評論在信息代碼...

// 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); 
      }); 
     }) 
    }) 
}) 

見下圖......這些都是我的控制檯上我收到錯誤 保持它記錄「發送」像80秒,然後我得到錯誤「UnhandledPromiseRejectionWarning」,我剛剛停留了2分鐘,我一直按'CTRL + C'。 Error I receive on my console

謝謝。

+0

該錯誤告訴你,你錯過了一個* .catch * –

+0

但我之前使用一個.catch(),並仍然得到類似這樣的請求TIMEDOUT(類似於),但我想添加延遲和擺脫這個錯誤.. – Tayyab

+0

這不是推入陣列後。因爲循環中的異步程序不能信任數組中的所有內容。 'Promise.all'應該保存在'setTimeout(function(){},0);'中。接下來是嘗試'async.waterfall'就像一次執行n個數字,然後繼續下一步連接。我可以給你一個正常js的示例。相應地實施。 – Priya

回答

1

async.each可能是你的情況更合適,檢查async.each

Promise.all()犯規在這種情況下,似乎正確,因爲方法返回一個承諾,當迭代參數中的所有promise均已解析或迭代參數不包含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) { 

    }); 

}); 
+0

我收到* * UnhandledPromiseRejectionWarning:未處理的承諾拒絕(拒絕ID:1):[object Object] ** – Tayyab

+0

我認爲它發送的請求太多了,現在我添加了catch方法並且在這種情況下接收到「Socket掛起」錯誤 – Tayyab

+0

您應該使用eachLimit (),這限制了併發請求的數量。檢查文檔:https://caolan.github.io/async/docs.html#eachLimit –

0

你可以使用一個僞遞歸方法陸續慢慢遍歷一個請求:

var finished=new Promise(function(resolve){ 
    (function iterate(index=0) { 
     var link=linksArray[index]; 
     var appID = link.match(/id=.*/g) 
     var instr = appID.toString(); 
     var appIDSliced = instr.slice(3) 
     var promise=store.app({id: appIDSliced});    
     promise.then(function(value){ 
      promiseStack.push(value); 
      if(index<linksArray.length) return iterate(index+1); 
      resolve(promiseStack); 
     }); 
    })(); 
}); 

finished.then(function(responses){ 
//your promise all code 
}); 
+0

你沒有使用任何.catch()...它不會像任何警告那樣顯示我在控制檯中? – Tayyab

+0

那麼我的兩個循環......和foreach ......我應該在「迭代」函數中使用它們嗎? @ Jonas-w – Tayyab

+1

@tayyab這不是一個複製粘貼運行的答案。您需要做一些額外的工作才能使其運行。這只是實現forEach循環,它可能已經工作,但你也可以實現這樣的for循環... –

0

for loop,當你推store.app({id: appIDSliced}) &我猜它開始請求服務器從而在突發模式。 Promise.all正在解決正在卡住的請求。

爲什麼不運行n numbers at a time並讓它們跟隨,直到所有服務器請求完成。這樣大多數請求之間會有延遲,因爲在任何時間點都會有最多5個請求運行,而不是突發執行。

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);
<div id="here"></div>

+0

沒有Promise.all沒有打到服務器,它只是等待早先發送的承諾被解決 –

+0

是啊這反過來調用'store.app({id:appIDSliced})'。並在問題說明中以突發模式進行。 – Priya

+0

它只是觀察由store.app發送的promise請求的狀態,當狀態從pending到fullfilled發生變化時,它只觸發Promise.all它不會調用本身返回的函數 –

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); 
    }) 
} 

一個簡單的和更短的代碼的錯誤處理。