Let's say I have a "JsonEditor" module (just for the example) which has 3 functions: get(), setProperty() and save().
Here is the code (the question follows):
var fs = require('fs')
, q = require('q');
var jsonEditorModule = (function() {
return {
get: function(jsonPath) {
// ...
},
save: function(jsonObject, jsonPath) {
var qJson = q.defer();
var jsonContent = JSON.stringify(jsonObject, null, 2);
fs.writeFile(jsonPath, jsonContent, function(err) {
if(err) {
qJson.reject(err);
}
else {
qJson.resolve();
}
});
return qJson.promise;
},
setProperty: function(prop, value, jsonPath) {
var self = this;
var qJson = q.defer();
this.get(jsonPath)
.then(
function(jsonObject) {
// Set the property
jsonObject[prop] = value;
// Save the file
self.save(jsonObject, jsonPath)
.then(
function() {
qJson.resolve();
},
function() {
qJson.reject();
},
);
}
);
return qJson.promise;
},
};
})();
module.exports = jsonEditorModule;
See the then() right after the save() in the setProperty() function ?
It looks stupid, right ?
Do I need to manually resolve() and reject() my promise ? Can't I just transfer the save() behavior to my setProperty() promise ?
Hope the question is clear enough (and not too stupid).
Thanks
Let's say I have a "JsonEditor" module (just for the example) which has 3 functions: get(), setProperty() and save().
Here is the code (the question follows):
var fs = require('fs')
, q = require('q');
var jsonEditorModule = (function() {
return {
get: function(jsonPath) {
// ...
},
save: function(jsonObject, jsonPath) {
var qJson = q.defer();
var jsonContent = JSON.stringify(jsonObject, null, 2);
fs.writeFile(jsonPath, jsonContent, function(err) {
if(err) {
qJson.reject(err);
}
else {
qJson.resolve();
}
});
return qJson.promise;
},
setProperty: function(prop, value, jsonPath) {
var self = this;
var qJson = q.defer();
this.get(jsonPath)
.then(
function(jsonObject) {
// Set the property
jsonObject[prop] = value;
// Save the file
self.save(jsonObject, jsonPath)
.then(
function() {
qJson.resolve();
},
function() {
qJson.reject();
},
);
}
);
return qJson.promise;
},
};
})();
module.exports = jsonEditorModule;
See the then() right after the save() in the setProperty() function ?
It looks stupid, right ?
Do I need to manually resolve() and reject() my promise ? Can't I just transfer the save() behavior to my setProperty() promise ?
Hope the question is clear enough (and not too stupid).
Thanks
Share Improve this question asked Mar 5, 2015 at 15:15 MaslowMaslow 1,1049 silver badges23 bronze badges 1- Look here and see if you can rework you call structure to set up a chain stackoverflow./questions/12461589/… – Steve Mitcham Commented Mar 5, 2015 at 15:20
2 Answers
Reset to default 2What you want to achieve is described here: chaining, basically if a handler returns a promise (let's call it innerPromiseFromHandler
) then the handlers of the .then
which was defined on the previous promise will be executed when the innerPromiseFromHandler
gets a resolution value:
var jsonEditorModule = (function() {
return {
get: function(jsonPath) {
return Q.delay(1000).then(function () {
document.write('get...<br/>');
return 'get';
});
},
save: function(result) {
return Q.delay(1000).then(function () {
document.write('save...<br/>');
return result + ' save';
});
},
setProperty: function(prop, value, jsonPath) {
return this.get(jsonPath)
.then(function(result) {
return jsonEditorModule.save(result);
});
}
};
})();
jsonEditorModule
.setProperty()
.then(function (result) {
document.write(result + ' finish');
})
<script src="http://cdnjs.cloudflare./ajax/libs/q.js/0.9.2/q.js"></script>
It looks stupid, right? Do I need to manually
resolve()
andreject()
my promise?
Right, and in fact this has an own name: Manually resolving/rejecting an extra promise is known as the stupid deferred antipattern.
Can't I just transfer the
save()
behavior to mysetProperty()
promise?
Yes, this is trivially possible - and it's builtin to the then
method: Calling .then()
returns a new promise for the return
value of your callbacks, even if that value is hidden in a promise.
var jsonEditorModule = {
get: function(jsonPath) {
// ...
},
save: function(jsonObject, jsonPath) {
return Q.ninvoke(fs, "writeFile", jsonPath, JSON.stringify(jsonObject, null, 2));
},
setProperty: function(prop, value, jsonPath) {
return this.get(jsonPath).then(function(jsonObject) {
// ^^^^^^
// Set the property
jsonObject[prop] = value;
// Save the file
return this.save(jsonObject, jsonPath);
// ^^^^^^
}.bind(this));
}
};