javascript中的同步迭代和异步迭代

所谓的迭代,用过es6的兄弟肯定已经接触过了,比如arr是一个数组,**[…arr]**还有for of 循环都是的。我说一说他背后的东西。

同步迭代

The interfaces for sync iteration ,借助typescript来写:

interface Iterable {
    [Symbol.iterator]() : Iterator;
}
interface Iterator {
    next() : IteratorResult;
}
interface IteratorResult {
    value : any;
    done : boolean;
}

总之,可迭代的对象(Iterable)上面有个[Symbol.iterator]方法,这个方法返回一个迭代器(Iterator),这个Iterator上面有个next方法,next方法调用的时候返回IteratorResult,IteratorResult的格式是::{ value:any, done:boolen }。。。那么,我们自己动手实现一个可迭代的对象:

方法1

const tongbuObj1 = {
  arr: [1, 2, 3],
  [Symbol.iterator]() {
    let length = this.arr.length;
    let index = 0;
    let it = {
      next: () => {
        return {
          done: index >= length,
          value: this.arr[index++]
        }
      }
    };
    return it;
  }
};

tongbuObj1上面由个arr, 我希望达到的目的是[…tongbuObj1]能和[…tongbuObj1.arr]一样,怎么做呢,就是实现[Symbol.iterator]方法就行了。

方法2

其实上面的方法可以再次化简,因为我们的要求是对象上有[Symbol.iterator]方法,并且这个方法返回一个对象,返回的对象上面有个next方法,那么下面这样是不是更简洁:

const tongbuObj2 = {
  arr: [1, 2, 3],
  index: 0,
  [Symbol.iterator]() {
    return this;
  },
  next() {
    return {
      done: this.index >= this.arr.length,
      value: this.arr[this.index++]
    }
  }
};

方法3

也许看到next的时候兄弟们已经想到了,这东西和es6里面生成器有点类似,其实就是这样,es6里面的生成器默认实现了可迭代接口,所以上面的例子还可以再次优化:

const tongbuObj3 = {
  arr: [1, 2, 3],
  * [Symbol.iterator]() {
    for (let i = 0; i < this.arr.length; i++) {
      yield this.arr[i];
    }
  }
};

方法1方法2方法3调用之后都是:

console.log([...tongbuObj1]);
console.log([...tongbuObj2]);
console.log([...tongbuObj3]);
// 结果是:
[ 1, 2, 3 ]
[ 1, 2, 3 ]
[ 1, 2, 3 ]

异步迭代

The interfaces for async iteration,借助typescript来写:

interface AsyncIterable {
    [Symbol.asyncIterator]() : AsyncIterator;
}
interface AsyncIterator {
    next() : Promise<IteratorResult>;
}
interface IteratorResult {
    value: any;
    done: boolean;
}

直接写一个例子,比较同步迭代和异步迭代吧,上代码:

// 先是同步迭代
const Async = 1;
const Bsync = 2;

function* gensync() {
  yield Async;
  yield Bsync;
}


async function fsync() {
  for (let v of gensync()) { // 1
    console.log('fsync', v);
  }
}

fsync();

// 下面是异步迭代

const aasync = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 111);
});

const basync = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3);
  }, 1113);
});

function* genasync() {
  yield aasync;
  yield basync;
}
async function fasync() {
  for await (let v of genasync()) { // 2
    console.log('fasync', v);
  }
}
fasync();

上面的代码输出:

fsync 1
fsync 2
fasync 1
fasync 3

总结:

同步迭代和异步迭代的区别,就在于next方法返回的是Promise还是普通值。甚至可以意会成2处的await是在等待v

参考文献:
https://exploringjs.com/es2018-es2019/ch_asynchronous-iteration.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值