Javascript “承诺内的范围变更”;然后";方法

Javascript “承诺内的范围变更”;然后";方法,javascript,node.js,coffeescript,promise,q,Javascript,Node.js,Coffeescript,Promise,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 file

我编写了以下程序,每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()
似乎
@processFile
不在范围内。如何修复此问题?

CoffeeScript包含保留词汇上下文的“胖箭头”。(就像ES6中的JavaScript一样)

无论何时要保留
值,请使用
=>
而不是
->

@x = 5
someFnCall someArg
.then (result) => console.log @x  # this will work
(注意,在高度并行和密集的工作中,这可能会很慢-您可能希望使用支持上下文的promise库,而不是像Bluebird一样)

CoffeeScript包含保留词汇上下文的“胖箭头”。(就像ES6中的JavaScript一样)

无论何时要保留
值,请使用
=>
而不是
->

@x = 5
someFnCall someArg
.then (result) => console.log @x  # this will work

(请注意,在高度并行和密集的工作中,这可能会很慢-您可能希望使用支持上下文的promise库,如Bluebird)

我不知道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的一个匿名函数中被调用。这意味着
这个
范围不是您的文件处理器的实例。

我不知道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
范围不是您的FileProcessor的实例。

Q.all
行中的
this.processFile
将抛出一个错误,因为
this
在非严格模式下设置为全局上下文,在其他情况下根据承诺/A+规范未定义。类似地,
Q.delay(this.delay)
在第二个
中。然后
将出错,最后一个
此。processFiles
将工作,虽然未设置
值。
Q.all
行中的
此.processFile
将抛出错误,因为
在非严格模式下设置为全局上下文,并根据承诺/a+规范未定义其他值。同样,第二个
中的
Q.delay(this.delay)
。然后
将出错,最后一个
this.processFiles
将起作用,但没有
this
值集。