简体   繁体   中英

Promisify callback style with optional arguments and run multiple times

I'm trying to Promisify with bluebird this function that has an optional second argument (weight) and it's just not working out whether I try to the do just the method or the whole object.

  RateLimit.prototype.incr = function(keys, weight, callback) {
    var args, err, _ref, _ref1;
    if (arguments.length === 2) {
      _ref = [1, weight], weight = _ref[0], callback = _ref[1];
    }
    try {
      _ref1 = this.scriptArgs(keys, weight), keys = _ref1[0], args = _ref1[1];
    } catch (_error) {
      err = _error;
      return callback(err);
    }
    return this["eval"].exec(this.checkIncrFn, keys, args, (function(_this) {
      return function(err, result) {
        return callback(err, __indexOf.call(_this.constructor.DENIED_NUMS, result) >= 0);
      };
    })(this));
  };

Original is here ( https://github.com/dudleycarr/ratelimit.js/blob/master/src/rate_limit.coffee ) but coffeescript so figured this compiled version is a bit more universally readable.

I think a custom promisify would be needed?

Also, my end goal is to have this call in a regression test suite and be able to be run a configurable amount of times with the same keys and weight calling parameters and get an array of the results from each callback in my final callback.

something like this:

var runTimes = 5;
var runKey = ‘akey’;
var runWeight = 2;

var keyMap = Array(5).fill(runKey);

Promise.all(Promise.map(keyMap, (k, w) => pPromisifiedIncr(k, w))
.then((values) => {
  console.log(values);
}));

I've tried combinations of Array().fill().map and Promises.map but was unable to quite get it possibly due to issues with the initial Promisify itself. Thanks!

It's a little hard to see what you're trying to do, but here's an idea that shows a manaully promisified incr() and a use of Promise.map() to run it through an array of values:

RateLimit.prototype.incr: function(keys, weight, callback) {
    return new Promise((resolve, reject) => {
        let args;

        // callback argument is optional
        if (arguments.length === 2) {
            callback = weight;
            weight = 1;
        }

        // if this throws, it will automatically reject the promise
        [keys, args] = this.scriptArgs(keys, weight);
        this["eval"].exec(this.checkIncrFn.bind(this), keys, args, (err, result) => {
            if (err) {
                reject(err);
            } else {
                resolve(result.indexOf(this.constructor.DENIED_NUMS) > 0);
            }
        });
    });
}


var keys = [{weight: 1, key: 'akey1'}, {weight: 2, key: 'akey2'}, {weight: 3, key: 'akey3'}, {weight: 4, key: 'akey4'}];

Promise.map(keys, item => xxx.incr(item.key, item.weight)).then((values) => {
  console.log(values);
});

I can't say I follow all the details of what your .incr() function is trying to do or how it translates to straight Javascript, but this should give you a general idea of what you're trying to achieve.

If the .incr() method already works (and especially if it's part of a third party library that you're incorporating into your project), your best option would probably be to leave it the way it is, and create a separate method for the the promise version, in which case it's rather easy:

RateLimit.prototype.incrPromise = function(keys, weight) {
    var self = this;
    var args = arguments;

    return new Promise(function (resolve, reject) {
        var callback = function (err, result) {
            if(err) { reject(err); } else { resolve(result); }
        };

        self.incr.apply(self, Array.prototype.concat.call(args, callback));
    });
};

To use it:

var runTimes = 5;
var runKey = ‘akey’;
var runWeight = 2;

var keyMap = Array(5).fill(runKey);
var myRateLimit = new RateLimit(); // create RateLimit here    

Promise.all(Promise.map(keyMap, (k, w) => myRateLimit.incrPromise(k, w))
    .then((values) => {
        console.log(values);
    }));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM