2017-10-09 11 views
5

खपत करता है मुझे एक एपीआई के लिए रेट लिमिटर मिला है जिसका उपयोग मैं कर रहा हूं जो प्रति सेकंड 20 अनुरोधों की अनुमति देता है। सभी अनुरोध वादे आधारित हैं और प्रतिक्रिया होने पर एपीआई डेटा के साथ वादा का समाधान किया जाएगा।Promise.all मेरी सभी रैम

समस्या:

मैं सेटअप एक promiseArray जो 58k शामिल सभी प्रतिक्रिया की प्रतीक्षा करने का वादा किया। तो धीरे-धीरे स्मृति तब तक बढ़ रही है जब तक कि मैं स्मृति से बाहर नहीं हो जाता। मेरी विशिष्ट स्थिति में मुझे हल किए गए डेटा को मेरे then() पर पास करने की आवश्यकता नहीं है और डेटा मेरी सभी रैम खा रहा है।

कोड:

}).then(() => { 
    // 2. Crawl for all clanprofiles from these leaderboards 
    const promiseArray = [] 
    for (let i = 0; i < clanTags.length; i++) { 
     // Resolved data from getClanProfile() is eating up all my RAM 
     const p = backgroundScheduler.getClanProfile(clanTags[i], true) 
     promiseArray.push(p) 
    } 
    return Promise.all(promiseArray) 
    }).then(() => { 

तो वहाँ promiseArray जब तक इंतजार करने के लिए एक रास्ता है संकल्प लिया डेटा की जरूरत के बिना हल हो गई है?

+2

58,000 वादे ?! मुझे लगता है जैसे आपको कट ऑफ पॉइंट होना चाहिए। यदि आप एक्स से अधिक अनुरोध प्राप्त करते हैं, तो बस उनमें से कुछ को छोड़ दें। यदि आपको कई कनेक्शन मिल रहे हैं तो आपको किसी एक प्रकार की लोड संतुलन और एक से अधिक नोड प्रक्रिया में अपने सर्वर को चलाने पर विचार करना चाहिए। –

+2

मुझे संदेह है कि मूल वादे के साथ यह संभव नहीं है क्योंकि उनके पास यह जानने का कोई तरीका नहीं है कि संलग्न कॉलबैक में से कोई भी डेटा का उपयोग नहीं करेगा (जब तक कि वादा स्वयं जीसीडी न हो)। –

+3

प्रतिक्रिया डेटा संग्रहीत करने से बचने के लिए, आप 'वादाएरेप.push (p.then (() =>' सफलता ') कर सकते हैं)' 'उस डेटा को छोड़ देना चाहिए जो प्रत्येक वादा ले रहा है और अभी भी एक उपयोगी वादे वापस कर सकता है। चाहिए। मैं वहां थोड़ा अस्पष्ट हूं, इसलिए उत्तर के बजाय टिप्पणी। – SethWhite

उत्तर

3

यदि आपके पास 58k वादे, उनके संबंधित एसिंक ऑपरेशंस और उनके परिणाम डेटा एक साथ सक्रिय नहीं हैं, तो आप कम मात्रा में स्मृति का उपयोग करेंगे।

इसके बजाय आप एक बार में एक्स ऑपरेशंस को चलाने के लिए चाहते हैं और फिर जब कोई समाप्त होता है, तो आप एक ही समय में उड़ान में एक्स से अधिक नहीं होते हैं और कभी भी X से अधिक बार उपयोग में वादे नहीं करते हैं।

आप एक्स के उचित मूल्य के साथ प्रयोग कर सकते हैं। 1 का मान अनुक्रमिक संचालन है लेकिन आप अक्सर एक्स के कुछ उच्च मूल्य का उपयोग करके समग्र अंत तक ऑपरेशन समय में सुधार कर सकते हैं। यदि सभी अनुरोध एक ही मेजबान को मार रहे हैं , तो एक्स शायद 5-10 से अधिक नहीं है (क्योंकि एक दिया गया मेजबान वास्तव में एक साथ कई चीजें नहीं कर सकता है और इसे एक बार करने से पहले ऐसा करने के लिए कह सकता है, बस इसे धीमा कर देता है)।

यदि प्रत्येक अनुरोध एक अलग मेजबान के लिए है, तो आप एक्स को उच्च बनाने में सक्षम हो सकते हैं। प्रयोग आपको चोटी मेमोरी उपयोग और समग्र थ्रूपुट दोनों के लिए इष्टतम मूल्य प्रदान करेगा और कुछ हद तक आपकी विशिष्ट परिस्थितियों पर निर्भर करता है।

ब्लूबर्ड के Promise.map() में एक समेकन विकल्प है जो आपके लिए यह करेगा, लेकिन एक ही समय में केवल एक्स उड़ान के लिए कोड के कई तरीके हैं।

Make several requests to an API that can only handle 20 request a minute

How to execute promises in series?

unable to complete promises due to out of memory

Fire off 1,000,000 requests 100 at a time

How to make it so that I can execute say 10 promises at a time in javascript to prevent rate limits on api calls?

:

यहाँ के प्रबंधन के कुछ अन्य कोडन उदाहरण कितने एक समय में उड़ान में हैं


आप हल हो गई डेटा की जरूरत नहीं है, तो आप इसे जितनी जल्दी इस तरह जगह से GCed होने की अनुमति कर सकते हैं:

const p = backgroundScheduler.getClanProfile(clanTags[i], true).then(data => { 
     return 0;  // make resolved value just be a simple number 
        // so other data is now eligible for GC 
    }); 
    promiseArray.push(p)  

और, यहाँ एक सरल कार्यान्वयन कि एक सरणी iterates है एक ही समय में उड़ान में एक्स से अधिक अनुरोध नहीं:

// takes an array of items and a function that returns a promise 
// runs no more than maxConcurrent requests at once 
function mapConcurrent(items, maxConcurrent, fn) { 
    let index = 0; 
    let inFlightCntr = 0; 
    let doneCntr = 0; 
    let results = new Array(items.length); 
    let stop = false; 

    return new Promise(function(resolve, reject) { 

     function runNext() { 
      let i = index; 
      ++inFlightCntr; 
      fn(items[index], index++).then(function(val) { 
       ++doneCntr; 
       --inFlightCntr; 
       results[i] = val; 
       run(); 
      }, function(err) { 
       // set flag so we don't launch any more requests 
       stop = true; 
       reject(err); 
      }); 
     } 

     function run() { 
      // launch as many as we're allowed to 
      while (!stop && inflightCntr < maxConcurrent && index < items.length) { 
       runNext(); 
      } 
      // if all are done, then resolve parent promise with results 
      if (doneCntr === items.length) { 
       resolve(results); 
      } 
     } 

     run(); 
    }); 
} 
+0

एक कार्यान्वयन जोड़ा गया जो नियंत्रित करता है कि एक ही समय में "उड़ान में" कितने अनुरोध हैं। – jfriend00

संबंधित मुद्दे