HolyZheng / holyZheng-blog

草稿
36 stars 0 forks source link

ES6 iterators/generators, async/await #7

Open HolyZheng opened 6 years ago

HolyZheng commented 6 years ago

作者:holyZheng 转载请注明出处

iterators(迭代器)

An iterator is an object with a next method that returns { done, value } tuples.

定义就是:一个具有next()方法且该方法返回一个 {done, value}元组的对象,done表示是否遍历完,value表示这次遍历的成员值。原生具有iterator接口的数据结构有 String, Array, TypedArray, Map, 和 Set。

for-of 循环

for-of循环与iterator一起工作,会调用数据结构的next()方法,取得返回对象{done, value}的value值,当返回对象{done, value}的done的值为true时停止迭代。

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
  console.log(item); // 1
                     // 2
                     // 3
                     // 4
                     // 5
}

在for-of中我们可以使用breakcontinuereturn

const arr = [1, 2, 3, 4, 5];
for (let item of arr) {
  if (item > 4) {
    break;
  }
  if (0 !== item % 2) {
    continue;
  }
  console.log(item); // 2
                     // 4
}

Generators

generators 是 iterators 的一个子类,它是一个特殊的函数,可以停止和从停止的地方重新开始,generator 采用 function* 和 yield 操作符来实现它的功能。

应用:异步操作同步化表达

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

让其自动自行的其中一个方案:

run(gen);

让其自动执行的另一个方案: 
- Thunk函数,thunk函数就是只接受一个参数,并且该参数为回调函数,在回调中把执行权交回给generator。
```js
var fs = require('fs');
var thunkify = require('thunkify');
var readFileThunk = thunkify(fs.readFile);

var gen = function* (){
  var r1 = yield readFileThunk('/etc/fstab');
  console.log(r1.toString());
};

var g = gen();

var r1 = g.next();
r1.value(function (err, data) {
  if (err) throw err;
  g.next(data);
});

co模块

可以让我们的generator自动执行,原理是:当异步操作有了结果,就把执行权交回给generator让它继续往下执行。co模块底层就是在thunk函数的回调中或在promise的then方法中,将执行权回交给generator。所以在使用co模块的时候,yield运算符后面得表达式必须返回一个thunk函数或promise对象。

var co = require('co');
co(gen).then(function (){
  console.log('Generator 函数执行完成');
});;
HolyZheng commented 6 years ago

async/ await

async和await可以让我们更加简单得处理异步操作,通过跟promise配合,我们可以完全像处理同步操作一样处理异步操作。

注意事项,如果多个异步操作之间没有先后关系,我们应该通过promise.all([promiseA, promiseB, promiseC])来并行的执行它们。

let [foo, bar] = await Promise.all([getFoo(), getBar()]);
let firstFinishPromise = await Promise.race([getFoo(), getBar()]); // 第一个处理完的promise