IsGenerator 实现

IsGenerator implementation

我之前依赖于以下如何检测生成器的定义:

function isGenerator(func) {
    return func instanceof Function && func.constructor.name === 'GeneratorFunction';
}

从那时起,我遇到了各种其他验证,包括检查原型上的 nextthrow 函数。

有没有办法在 NodeJS 0.10 的范围内实现 isGenerator 功能被认为是全面的 - 5.x?

我打算在其中使用的应用程序是选择任何生成器(甚至迭代器),并将其包装成一个使用函数 nextthrow 的承诺。

为此,我使用了来自 here:

的修改示例
/////////////////////////////////
// Generator-to-Promise adapter;
function asyncAdapter(generator) {
    return function () {
        var g = generator.apply(this, arguments);

        function handle(result) {
            if (result.done) {
                return Promise.resolve(result.value);
            }
            return Promise.resolve(result.value)
                .then(function (res) {
                    return handle(g.next(res));
                }, function (err) {
                    return handle(g.throw(err));
                });
        }

        return handle(g.next());
    }
}

I previously relied on the following definition of how to detect a generator […]

它不检测生成器,它检测生成器函数。而且你不应该 依赖 这样的东西,因为每个函数都可以 return 生成器。

Is there a way to implement isGeneratorFunction to be considered comprehensive within the realm of NodeJS 0.10 - 5.x?

是的,有 are a few,在您展示的 .constructor.name 方法旁边,也可以使用 instanceof.toString()

The application in which I intend to use is to pick up any generator (or even iterator)

不要变魔术。只需让用户决定他们是否要使用生成器,并让他们在这种情况下显式调用您的函数。

ES 6

9.2.6 GeneratorFunctionCreate (kind, ParameterList, Body, Scope, Strict)

The abstract operation GeneratorFunctionCreate requires the arguments: kind which is one of (Normal, Method), a parameter list production specified by ParameterList, a body production specified by Body, a Lexical Environment specified by Scope, and a Boolean flag Strict.

GeneratorFunctionCreate performs the following steps:

  1. Let functionPrototype be the intrinsic object %Generator%.
  2. Let F be FunctionAllocate(functionPrototype, Strict, "generator").
  3. Return FunctionInitialize(F, kind, ParameterList, Body, Scope).

所以你可以通过检查原型来接近 是否适合发电机。 Object.getPrototypeOf 让我们测试 functionPrototype 的值是否是内置的 %Generator% 尽管代理对象可以控制 Object.getPrototypeOf 的结果。将生成器的代理视为生成器可能是一件好事。

function isGenerator(functionThatMightBeGenerator) {
  function *nullGenerator() {}
  return (functionThatMightBeGenerator
          &&  Object.getPrototypeOf(functionThatMightBeGenerator)
          === Object.getPrototypeOf(nullGenerator));
}

如果您担心区分生成器代理和生成器,您可以查看 14.5.14#6.g.i。这要求 class 声明禁止生成器作为超类型,因此可以直接检查 FunctionKind 内部插槽是否为 "generator".

这可能有点矫枉过正,但类似于

function isGeneratorAndProbablyNotProxyThereof(functionThatMightBeGenerator) {
  function *nullGenerator() {}
  if (!functionThatMightBeGenerator
      || (Object.getPrototypeOf(functionThatMightBeGenerator)
          !== Object.getPrototypeOf(nullGenerator))) {
    return false;
  }
  function defineAndThrowawaySubClass(superType) {
    class C extends superType {}
  }
  let isGenerator = false;
  try {
    defineAndThrowawaySubClass(functionThatMightBeGenerator);
  } catch (e) {
    isGenerator = e instanceof TypeError;
  }
  return isGenerator;
}

应该这样做,尽管有足够动机的代理作者也可能会欺骗它。