Изменения области внутри методов promise «then»

#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 значения.