#javascript #node.js #coffeescript #promise #q
#javascript #node.js #coffeescript #обещание #q
Вопрос:
Я написал следующую программу, которая обрабатывает все файлы в каталоге каждые N миллисекунд:
fs = require "fs"
Q = require "q"
class FileProcessor
constructor: (options) ->
@dir = options.dir
@delay = options.delay
processFiles: ->
Q.nfcall fs.readdir, @dir
.then (files) -> Q.all files.map (file) -> @processFile file # <-- Error!
.then -> Q.delay @delay
.then -> @processFiles()
.done()
processFile: (file) ->
deferred = Q.defer()
# Does some stuff.
return deferred.promise
fp = new FileProcessor(dir: "photos", delay: 1000)
fp.processFiles()
В строке 11 я получаю эту ошибку:
TypeError: undefined is not a function
Кажется @processFile
, это не входит в область видимости. Как это исправить?
Ответ №1:
CoffeeScript содержит «жирные стрелки», которые сохраняют лексический контекст. (Точно так же, как JavaScript в ES6).
Всякий раз, когда вы хотите сохранить this
значение, используйте =>
вместо ->
:
@x = 5
someFnCall someArg
.then (result) => console.log @x # this will work
(Обратите внимание, что при высокой параллельности и интенсивной работе это может быть медленным — возможно, вы захотите использовать библиотеку promise, которая поддерживает контекст, например Bluebird)
Ответ №2:
Я не знаю coffeescript, поэтому я отвечу на обычном JS:
Ваша processFiles
функция преобразуется в:
FileProcessor.prototype.processFiles = function() {
return Q.nfcall(fs.readdir, this.dir).then(function(files) {
return Q.all(files.map(this.processFile));
}).then(function() {
return Q.delay(this.delay);
}).then(this.processFiles).done();
};
Вы можете ясно видеть, что this.processFile
вызывается внутри анонимной функции, переданной then . Это означает, что this
область действия не является экземпляром вашего файлового процессора.
Комментарии:
1.
this.processFile
вQ.all
строке будет выдана ошибка, посколькуthis
для глобального контекста установлено значение в нестрогом режиме и в противном случае не определено в соответствии со спецификацией Promises / A .2. Аналогично,
Q.delay(this.delay)
во втором.then
произойдет ошибка, последнееthis.processFiles
будет работать, хотя и без установленногоthis
значения.