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
2 Answers
Reset to default 7use 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.