小工具iterate学习(加快类数组的遍历速度)

github地址

  • 这是一个能在MapSet使用数组方法(如:map()filter(), reduce())。

  • 而且如果使用多个操作符时,能只迭代一次,而不是补个操作符迭代一次。大大加快运行速度,对于运行一个很大的Set会有明显的效果。

这个包应用了ES6的Iterator的概念。默认可遍历的数据结构是具有Symbol.iterator的属性。通过运行next方法就可以获得如下对象

{value:值, done: 是否到最后};

包用法:

iterate(uris)
  .filter(uri => uri.startsWith('file://'))
  .map(uri => uri.substr('file:///'.length))
  .toSet()

简单说,toSet()之前都是在不停装饰实例,成为一个新的遍历器。之后才开始迭代。

iterate(uris)

上面逻辑是:

function iterate(collection: Iterator | Iterable): IteratorWithOperators {
    return new IteratorWithOperators(toIterator(collection))
}

就是用被传入对象的遍历器生成一个新的可遍历对象。

export class IteratorWithOperators implements IterableIterator {
    /**
     * @param source Iterator to wrap
     */
    constructor(private source: Iterator) {}

    /**
     * Returns a `{ value, done }` object that adheres to the Iterator protocol
     */
    next(): IteratorResult {
        return this.source.next()
    }

    /**
     * The presence of this method makes the Iterator itself Iterable.
     * This makes it possible to pass it to `for of` and Iterable-accepting functions like `Array.from()`
     */
    [Symbol.iterator](): this {
        return this
    }

    /**
     * Returns a new Iterator by running each element thru iteratee
     */
    map(iteratee: (value: T) => R): IteratorWithOperators {
        return new IteratorWithOperators(new MapIterator(this.source, iteratee))
    }
....

能看出其实现了[Symbol.iterator]的方法,所以是可遍历的。

我们看下map操作的实现就明白为何会只迭代一次。直接看
new MapIterator(this.source, iteratee)

export class MapIterator implements Iterator {
    constructor(private source: Iterator, private iteratee: (value: T) => R) {}

    next(): IteratorResult {
        const { value, done } = this.source.next()
        return { value: !done && this.iteratee(value), done } as IteratorResult
    }
}

可以看出,实例生成时,支撑保存了遍历器与处理方法。

所以当最后调用IteratorWithOperators的非操作符的遍历方法时,会自动去调用遍历器的next方法,从最底层开始,一层一层的往上调用操作符的逻辑,所以最底层遍历结束,整体也进入最后结束轮,仅需遍历一次。

PS: 也可以看出所有逻辑都是同步的。其实使用RxJS也是可以只遍历一次,如:

of([1,2,3,4]).pipe(tap(....),map(...),mergeMap(....)).subscribe(cb)

但这个包可以让我们类似用原生的方法去操作,比较亲切。

如果觉得文章对你有点用的话,麻烦拿出手机,这里有一个你我都有的小福利(每天一次): 打开支付宝首页搜索“8601304”,即可领红包。谢谢支持

你可能感兴趣的:(小工具iterate学习(加快类数组的遍历速度))