javascript - चलाया जा रहा वादा की सीमा सीमित करें




node.js promise (3)

गला घोंटना-वादा मॉड्यूल का उपयोग करें:

https://www.npmjs.com/package/throttled-promise

var ThrottledPromise = require('throttled-promise'),
    promises = [
        new ThrottledPromise(function(resolve, reject) { ... }),
        new ThrottledPromise(function(resolve, reject) { ... }),
        new ThrottledPromise(function(resolve, reject) { ... })
    ];

// Run promises, but only 2 parallel
ThrottledPromise.all(promises, 2)
.then( ... )
.catch( ... );

मैं एक वादा फ़ंक्शन रैपर की तलाश कर रहा हूं जो किसी दिए गए वादे के चलते / थ्रॉटल को सीमित कर सकता है ताकि उस वादे का केवल एक सेट संख्या एक निश्चित समय पर चल रही हो।

delayPromise नीचे के मामले में, कभी भी समवर्ती रूप से नहीं delayPromise चाहिए, उन्हें सभी को पहले आओ-पहले पाओ के क्रम में एक बार चलाना चाहिए।

import Promise from 'bluebird'

function _delayPromise (seconds, str) {
  console.log(str)
  return Promise.delay(seconds)
}

let delayPromise = limitConcurrency(_delayPromise, 1)

async function a() {
  await delayPromise(100, "a:a")
  await delayPromise(100, "a:b")
  await delayPromise(100, "a:c")
}

async function b() {
  await delayPromise(100, "b:a")
  await delayPromise(100, "b:b")
  await delayPromise(100, "b:c")
}

a().then(() => console.log('done'))

b().then(() => console.log('done'))

कैसे इस तरह एक कतार पाने के लिए पर कोई विचार स्थापित?

मेरे पास अद्भुत Benjamin Gruenbaum से "बहस" समारोह है। मुझे इसे संशोधित करने और देरी नहीं करने के आधार पर एक वादे को विफल करने की आवश्यकता है।

export function promiseDebounce (fn, delay, count) {
  let working = 0
  let queue = []
  function work () {
    if ((queue.length === 0) || (working === count)) return
    working++
    Promise.delay(delay).tap(function () { working-- }).then(work)
    var next = queue.shift()
    next[2](fn.apply(next[0], next[1]))
  }
  return function debounced () {
    var args = arguments
    return new Promise(function (resolve) {
      queue.push([this, args, resolve])
      if (working < count) work()
    }.bind(this))
  }
}

मुझे नहीं लगता कि ऐसा करने के लिए कोई लाइब्रेरी है, लेकिन यह वास्तव में अपने आप को लागू करने के लिए काफी सरल है:

function queue(fn) { // limitConcurrency(fn, 1)
    var q = Promise.resolve();
    return function(x) {
        var p = q.then(function() {
            return fn(x);
        });
        q = p.reflect();
        return p;
    };
}

कई समवर्ती अनुरोधों के लिए यह थोड़ा मुश्किल हो जाता है, लेकिन साथ ही साथ किया जा सकता है।

function limitConcurrency(fn, n) {
    if (n == 1) return queue(fn); // optimisation
    var q = null;
    var active = [];
    function next(x) {
        return function() {
            var p = fn(x)
            active.push(p.reflect().then(function() {
                active.splice(active.indexOf(p), 1);
            })
            return [Promise.race(active), p];
        }
    }
    function fst(t) {
        return t[0];
    }
    function snd(t) {
        return t[1];
    }
    return function(x) {
        var put = next(x)
        if (active.length < n) {
            var r = put()
            q = fst(t);
            return snd(t);
        } else {
            var r = q.then(put);
            q = r.then(fst);
            return r.then(snd)
        }
    };
}

Btw, आप अभिनेता मॉडल और CSP पर एक नज़र रखना चाहते हो सकता है। वे इस तरह की चीजों से निपटने को सरल बना सकते हैं, उनके लिए कुछ जेएस लाइब्रेरी भी हैं।

उदाहरण

import Promise from 'bluebird'

function sequential(fn) {
  var q = Promise.resolve();
  return (...args) => {
    const p = q.then(() => fn(...args))
    q = p.reflect()
    return p
  }
}

async function _delayPromise (seconds, str) {
  console.log(`${str} started`)
  await Promise.delay(seconds)
  console.log(`${str} ended`)
  return str
}

let delayPromise = sequential(_delayPromise)

async function a() {
  await delayPromise(100, "a:a")
  await delayPromise(200, "a:b")
  await delayPromise(300, "a:c")
}

async function b() {
  await delayPromise(400, "b:a")
  await delayPromise(500, "b:b")
  await delayPromise(600, "b:c")
}

a().then(() => console.log('done'))
b().then(() => console.log('done'))

// --> with sequential()

// $ babel-node test/t.js
// a:a started
// a:a ended
// b:a started
// b:a ended
// a:b started
// a:b ended
// b:b started
// b:b ended
// a:c started
// a:c ended
// b:c started
// done
// b:c ended
// done

// --> without calling sequential()

// $ babel-node test/t.js
// a:a started
// b:a started
// a:a ended
// a:b started
// a:b ended
// a:c started
// b:a ended
// b:b started
// a:c ended
// done
// b:b ended
// b:c started
// b:c ended
// done

श्रृंखला में async प्रक्रियाओं को चलाने का क्लासिक तरीका async.js का उपयोग async.js और async.series() उपयोग async.series() । यदि आप वादे पर आधारित कोड पसंद करते हैं तो async.js का एक वादा संस्करण है: async-q

async-q आप एक बार फिर series उपयोग कर सकते हैं:

async.series([
    function(){return delayPromise(100, "a:a")},
    function(){return delayPromise(100, "a:b")},
    function(){return delayPromise(100, "a:c")}
])
.then(function(){
    console.log(done);
});

एक ही समय में उनमें से दो को चलाने से a और b समवर्ती रूप से चलेगा, लेकिन प्रत्येक के भीतर वे अनुक्रमिक होंगे:

// these two will run concurrently but each will run
// their array of functions sequentially:
async.series(a_array).then(()=>console.log('a done'));
async.series(b_array).then(()=>console.log('b done'));

यदि आप b को चलाना चाहते हैं, .then() इसे तब .then() में डालें:

async.series(a_array)
.then(()=>{
    console.log('a done');
    return async.series(b_array);
})
.then(()=>{
    console.log('b done');
});

यदि आप क्रमिक रूप से चलने के बजाय प्रत्येक प्रक्रिया को समवर्ती रूप से चलाने के लिए प्रत्येक को सीमित करना चाहते हैं तो आप parallelLimit() उपयोग कर सकते हैं:

// Run two promises at a time:
async.parallelLimit(a_array,2)
.then(()=>console.log('done'));

Async-q डॉक्स पढ़ें: https://github.com/dbushong/async-q/blob/master/READJSME.md







bluebird