代码之家  ›  专栏  ›  技术社区  ›  vitaly-t

验证迭代器与异步迭代器类型

  •  1
  • vitaly-t  · 技术社区  · 4 年前

    JavaScript中有没有已知的技巧来区分 Iterator 和 AsyncIterator ,而不触发迭代?

    我正在尝试实现以下类型检查器:

    function isAsyncIterator<T>(i: Iterator<T> | AsyncIterator<T>): boolean {
        // returns:
        //  - true, if i is an asycnronous iterator
        //  - false, if i is a syncronous iterator
    }
    

    我知道这个电话 next 我会这样告诉我们,但我需要它在我无法触发迭代的时候。

    此外,尽管我在TypeScript中给出了示例,但我需要在运行时严格检查它。

    0 回复  |  直到 4 年前
        1
  •  2
  •   Bergi    4 年前

    这是不可能的。 遍历器 是由协议定义的,而不是由有形财产定义的,因此 halting problem 如果不进行实际迭代,就无法确定对象是否是迭代器。另见类似问题 What is the technical definition of a Javascript iterable and how do you test for it? .

    然而,有一些很好的启发式方法可以检测大多数表现良好的迭代器实现和所有内置迭代器:

    • 迭代器通常是可移植的(不能在 for … of 循环(否则会限制它们的用途),并将为此委托给它们自己。所以

      function isIterator(obj) {
          if (Object(obj) !== obj) return false;
          const method = obj[Symbol.iterator];
          if (typeof method != 'function') return false;
          const iter = method.call(obj);
          return iter === obj;
      }
      function isAsyncIterator(obj) {
          if (Object(obj) !== obj) return false;
          const method = obj[Symbol.asyncIterator];
          if (typeof method != 'function') return false;
          const aIter = method.call(obj);
          return aIter === obj;
      }
      
    • 迭代器继承自内置函数 %IteratorPrototype% .直到 iterator helpers proposal 将介绍全球 Iterator 这些对象的访问和测试有点麻烦,但还是有可能的。

      const GeneratorPrototype = Object.getPrototypeOf(function*() {}).prototype;
      const IteratorPrototype = Object.getPrototypeOf(GeneratorPrototype);
      const AsyncGeneratorPrototype = Object.getPrototypeOf(async function*() {}).prototype;
      const AsyncIteratorPrototype = Object.getPrototypeOf(AsyncGeneratorPrototype);
      
      function isIterator(obj) {
          return IteratorPrototype.isPrototypeOf(obj);
      }
      function isAsyncIterator(obj) {
          return AsyncIteratorPrototype.isPrototypeOf(obj);
      }
      

      (当然,和其他人一样 instanceof 检查,这不适用于其他领域的对象,这就是为什么我推荐第一种方法。)