2017-10-09 15 views
5

Tôi đã có giới hạn tốc độ cho API tôi đang sử dụng, cho phép 20 yêu cầu mỗi giây. Tất cả các yêu cầu đều dựa trên lời hứa và lời hứa sẽ được giải quyết với dữ liệu API khi có phản hồi.Promise.all tiêu thụ tất cả RAM của tôi

Vấn đề:

tôi thiết lập một promiseArray chứa 58k hứa hẹn tất cả chờ đợi một phản ứng. Vì vậy, từ từ bộ nhớ đang tăng lên cho đến khi tôi hết bộ nhớ. Trong tình huống cụ thể của tôi, tôi không cần phải chuyển dữ liệu đã giải quyết đến then() và dữ liệu đang ăn hết tất cả RAM của tôi.

Mã:

}).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(() => { 

Vậy là có một cách để chờ đợi cho đến khi promiseArray được giải quyết mà không cần những dữ liệu giải quyết?

+2

58.000 lời hứa ?! Âm thanh với tôi như bạn cần phải có một điểm cắt đứt. Nếu bạn nhận được nhiều hơn X yêu cầu, chỉ cần từ bỏ một số yêu cầu. Nếu bạn đang nhận được nhiều kết nối, bạn nên xem xét một số loại cân bằng tải và chạy máy chủ của bạn trong quá trình nhiều hơn một nút. –

+2

Tôi nghi ngờ điều này là không thể với Promises bản địa bởi vì họ không có cách nào biết rằng không có callbacks đính kèm sẽ sử dụng dữ liệu (cho đến khi lời hứa chính nó là GC'd). –

+3

Để tránh lưu trữ dữ liệu phản hồi, bạn có thể thực hiện 'promiseArray.push (p.then (() => 'success')) 'Điều đó sẽ làm giảm dữ liệu mà mỗi lời hứa đang mang và vẫn trả về lời hứa có thể sử dụng được. Nên. Tôi hơi mờ ở đó, vì thế nhận xét thay vì trả lời. – SethWhite

Trả lời

3

Bạn sẽ sử dụng bộ nhớ ít hơn nếu bạn không bao giờ có lời hứa 58k, các hoạt động không đồng bộ liên quan và dữ liệu kết quả của chúng hoạt động cùng một lúc. Thay vào đó bạn muốn chạy các hoạt động X cùng một lúc và sau đó khi kết thúc, bạn bắt đầu một lần tiếp theo với không bao giờ nhiều hơn X trong chuyến bay cùng một lúc và không bao giờ nhiều hơn X hứa hẹn sử dụng cùng một lúc.

Bạn có thể thử nghiệm với giá trị thích hợp X. Giá trị 1 là hoạt động tuần tự nhưng bạn thường có thể cải thiện tổng thời gian hoạt động từ đầu đến cuối bằng cách sử dụng một số giá trị cao hơn X. Nếu tất cả yêu cầu đều gặp cùng một máy chủ thì X có thể không quá 5-10 (vì một máy chủ nhất định không thể thực hiện nhiều thứ cùng một lúc và yêu cầu nó làm nhiều hơn một lúc có thể làm chậm).

Nếu mọi yêu cầu đến một máy chủ lưu trữ khác nhau, thì bạn có thể làm cho X cao hơn. Thử nghiệm sẽ cung cấp cho bạn một giá trị tối ưu cho cả việc sử dụng bộ nhớ cao điểm và thông lượng tổng thể và phần nào phụ thuộc vào hoàn cảnh cụ thể của bạn.

Bluebird's Promise.map() có tùy chọn đồng thời sẽ thực hiện việc này cho bạn, nhưng cũng có nhiều cách để mã chỉ cho X trong chuyến bay cùng một lúc.

Dưới đây là một số ví dụ mã hóa khác trong việc quản lý bao nhiêu là trong chuyến bay tại một thời điểm:

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?


Nếu bạn không cần những dữ liệu giải quyết, bạn có thể cho phép nó được GCed sớm bằng cách thay thế nó như thế này:

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)  

Và, đây là một thực hiện đơn giản mà lặp một mảng không quá X yêu cầu chuyến bay cùng một lúc:

// 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

Đã thêm một triển khai kiểm soát số lượng yêu cầu "đang bay" cùng một lúc. – jfriend00

Các vấn đề liên quan