最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Chaining promises with multiple arguments - Stack Overflow

programmeradmin4浏览0评论

I have just started using promises in Javascript and I'm wondering if there is a way to reduce the boilerplate code of wrapping every then callback in a function? I find myself doing this a lot and wondering if there is a better way

For example in my getSettings function below it either returns a settings model from the database (then) or a default settings model (catch).

var getSettings = function(instance, id, mode) {
    return findByInstance(instance)
        .then(function(data) {
            return useModelFromData(data, id, mode);
        })
        .catch(function() {
            return useDefaultModel(id, mode)
        });
};

var useModelFromData = function(data, id, mode) {
    var settings = data.model.settings;
    applyFeatures(settings, id, mode);
    return data.model;
};

var useDefaultModel = function(id, mode) {
    var model = myModel.getDefaultModel();
    applyFeatures(model.settings, id, mode);
    return model;
};

I know that if the then callback takes a single argument and returns a value you can do the following shortcut:

get('some_url').then(JSON.parse).then(function(response) {
  console.log("response", response);
});

Is there any shortcut I can do for multiple arguments?

I have just started using promises in Javascript and I'm wondering if there is a way to reduce the boilerplate code of wrapping every then callback in a function? I find myself doing this a lot and wondering if there is a better way

For example in my getSettings function below it either returns a settings model from the database (then) or a default settings model (catch).

var getSettings = function(instance, id, mode) {
    return findByInstance(instance)
        .then(function(data) {
            return useModelFromData(data, id, mode);
        })
        .catch(function() {
            return useDefaultModel(id, mode)
        });
};

var useModelFromData = function(data, id, mode) {
    var settings = data.model.settings;
    applyFeatures(settings, id, mode);
    return data.model;
};

var useDefaultModel = function(id, mode) {
    var model = myModel.getDefaultModel();
    applyFeatures(model.settings, id, mode);
    return model;
};

I know that if the then callback takes a single argument and returns a value you can do the following shortcut:

get('some_url').then(JSON.parse).then(function(response) {
  console.log("response", response);
});

Is there any shortcut I can do for multiple arguments?

Share Improve this question asked Nov 2, 2014 at 1:30 DecrypterDecrypter 3,00012 gold badges41 silver badges60 bronze badges 1
  • spread works if you return an array of arguments - see the bluebird api for spread: github./petkaantonov/bluebird/blob/master/… – Ryan Quinn Commented Nov 2, 2014 at 1:41
Add a ment  | 

2 Answers 2

Reset to default 7

use bind and move the argument list around

var getSettings = function(instance, id, mode) {
    return findByInstance(instance)
        .then(useModelFromData.bind(null, id, mode))
        .catch(useDefaultModel.bind(null, id, mode));
};

var useModelFromData = function(id, mode, data) {
    var settings = data.model.settings;
    applyFeatures(settings, id, mode);
    return data.model;
};

var useDefaultModel = function(id, mode) {
    var model = myModel.getDefaultModel();
    applyFeatures(model.settings, id, mode);
    return model;
};

With bind you can set arguments to be prepended to the arguments list when the function is executed. So in this case id and mode will get prepended to the arguments that get passed to useModelFromData and useDefaultModel

I went through this today and this is what I came up with....

function p(func){
  var args=[];
  for(var i=1,end=arguments.length;i<end;i++)args.push(arguments[i]);
   return function(response){
     for(var i=0,end=args.length;i<end;i++){
       if(args[i]=='{response}')args[i]=response;
     }
    return func.apply(func,args);
   }
}

With p you wouldnt have needed to change the arguments of the functions your calling, you could have just done....

var getSettings = function(instance, id, mode) {
    return findByInstance(instance)
        .then(p(useModelFromData, '{response}', id, mode))
        .catch(p(useDefaultModel, id, mode));
};

Heres the page I came up with it on...
http://plnkr.co/edit/4EGDTk?p=preview
...you might find the other functions useful.

发布评论

评论列表(0)

  1. 暂无评论