问题
I'm using Node.js and Q to write server-side asynchronous code. I'm new to promises (and I'm new to asynchronous programming in general), and I'm having a bit of trouble that I haven't been able to solve by staring at the Q documentation. Here's my code (it's coffeescript - let me know if you want to see the javascript instead):
templates = {}
promises = []
for type in ['html', 'text']
promises.push Q.nfcall(fs.readFile
, "./email_templates/#{type}.ejs"
, 'utf8'
).then (data)->
# the problem is right here - by the time
# this function is called, we are done
# iterating through the loop, and the value
# of type is incorrect
templates[type] = data
Q.all(promises).then(()->
console.log 'sending email...'
# send an e-mail here...
).done ()->
# etc
Hopefully my comments explained the problem. I want to iterate through a list of types, and then run a chain of promises for each type, but the problem is that the value of type
is being changed outside of the scope of the promises. I realize that, for such a short list, I can just unroll the loop, but this is not a sustainable solution. How can I ensure that each promise sees a different yet locally correct value of type
?
回答1:
You have to encapsulate your data assignment closure in another closure, so that the value of type is preserved until the inner closure is executed.
For further details: http://www.mennovanslooten.nl/blog/post/62
回答2:
I don't know CoffeeScript, but this should work in JS:
var promises = [];
var templates = {};
var ref = ['html', 'text'];
for (var i = 0, len = ref.length; i < len; i++) {
var type = ref[i];
promises.push(Q.nfcall(fs.readFile, "./email_templates/" + type + ".ejs", 'utf8').then((function (type) {
return function (data) {
return templates[type] = data;
};
}(type))));
}
Q.all(promises).then(function() {
return console.log('sending email...');
// ...
}).done(function() {
// ...
});
Edit: CoffeeScript translation:
templates = {}
promises = []
for type in ['html', 'text']
promises.push Q.nfcall(fs.readFile
, "./email_templates/#{type}.ejs"
, 'utf8'
).then do (type)->
(data)->
templates[type] = data
Q.all(promises).then(()->
console.log 'sending email...'
).done ()->
console.log '...'
The part of importance being:
).then do (type)->
(data)->
templates[type] = data
来源:https://stackoverflow.com/questions/20294791/javascript-promises-with-q-closure-problems-in-promises