2013-11-29 3 views
1

Я использую Node.js и Q для написания асинхронного кода на стороне сервера. Я новичок в обещаниях (и я новичок в асинхронном программировании в целом), и у меня возникают проблемы, которые я не смог решить, глядя на Q-документацию. Вот мой код (это CoffeeScript - дайте мне знать, если вы хотите, чтобы увидеть JavaScript, а):Javascript и обещания с проблемами Q-закрытия в обещаниях

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 

Надеюсь, мои комментарии объяснил проблему. Я хочу выполнить итерацию по списку типов, а затем выполнить цепочку обещаний для каждого типа, но проблема в том, что значение type меняется за пределы объема обещаний. Я понимаю, что для такого краткого списка я могу просто развернуть цикл, но это не является устойчивым решением. Как я могу гарантировать, что каждое обещание видит другое, но локально правильное значение type?

ответ

3

Вы должны инкапсулировать закрытие ваших данных в другое закрытие, чтобы значение типа сохранялось до тех пор, пока не будет выполнено внутреннее закрытие.

Для получения более подробной информации: http://www.mennovanslooten.nl/blog/post/62

+0

Спасибо. Хотя я не копировал это решение точно, объяснение в этом сообщении в блоге помогло мне создать исправление. – jayhendren

1

не знаю CoffeeScript, но это должно работать в 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 перевода:

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 '...' 

Часть имеющих значение:

).then do (type)-> 
    (data)-> 
     templates[type] = data 
+0

Это в значительной степени именно сгенерированный JavaScript: http://goo.gl/K22IAd –

+0

@MattBall У меня есть дополнительное закрытие там (см. Непосредственное выражение функции). –

+0

Спасибо, Джон. Полагаю, я понимаю, что здесь происходит. Тем не менее, я принял другой ответ, потому что он предоставил ссылку на объяснение проблемы, что было более полезным, чем быстрое исправление. – jayhendren