找不到 koa.js 研讨会解决方案的解释,第一个练习

Can't find an explanation for koa.js workshop solution, exercise number one

它必须相当简单,但我无法理解 the beginning exercise from koa workshop 的解决方案。

测试:

var co = require('co');
var assert = require('assert');
var fs = require('./index.js');

describe('.stats()', function () {
  it('should stat this file', co(function* () {
    var stats = yield fs.stat(__filename);
    assert.ok(stats.size);
  }));
});

解决方案和任务:

var fs = require('fs');

/**
 * Create a yieldable version of `fs.stat()`:
 *
 *   app.use(function* () {
 *     var stats = yield exports.stat(__filename);
 *   })
 *
 * Hint: you can return a yieldable.
 */

exports.stat = function (filename) {
    return function (done) {
        fs.stat(filename, done);
    }
};

我对这个测试的看法是:co 库为我们运行生成器函数,fs.stat(__filename) 调用,returns

function (done) {
    fs.stat(filename, done);
}

那么,我只有一个问题:为什么匿名函数returns fs.stat()在同一个地方,它在哪里回调done?我已经记录了这个回调,它是带有 stats 对象作为传递参数的生成器 next() 方法,但是我在 co 中找不到任何关于回调注入的信息。这是如何运作的?提前谢谢你。

我无法在主 README.md 上找到此信息,但看起来 co 自动提供了对 thunks 的回调。所以在上面的例子中 co 提供了 done 回调并调用:

function (done) {
    fs.stat(filename, done);
}

如果出现错误,此回调预计主函数会 return 错误 (done(err);),如果一切正常:done(null, result);。之后将结果传递给生成器。这是 done 回调代码:

function () {
  if (called) return;
  called = true;
  next.apply(ctx, arguments);
}

好吧,让我们 return 来解决问题。 co 的 git README.md 说:

Thunk support only remains for backwards compatibility and may be removed in future versions of co.

所以让我们用 promises 将其重写为现代视图:

exports.stat = function(filename) {
  return new Promise((resolve, reject) => {
    fs.stat(filename, (err, stats) => {
      if (err) {reject(err);}
      resolve(stats);
    });
  });
};

我们用获取 filename 值的匿名函数包装承诺,并将其封装为 returning 承诺对象,这是受支持的 yieldablesco 中。此承诺以回调启动 fs.stat。如果一切正常,此回调 resolve 是承诺,否则 reject 是承诺。 resolved 结果 returns 进入生成器。