{"action":"created","issue":{"url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/7","repository_url":"https://api.github.com/repos/HolyZheng/holyZheng-blog","labels_url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/7/labels{/name}","comments_url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/7/comments","events_url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/7/events","html_url":"https://github.com/HolyZheng/holyZheng-blog/issues/7","id":333324730,"node_id":"MDU6SXNzdWUzMzMzMjQ3MzA=","number":7,"title":"ES6 iterators/generators, async/await","user":{"login":"HolyZheng","id":32334054,"node_id":"MDQ6VXNlcjMyMzM0MDU0","avatar_url":"https://avatars2.githubusercontent.com/u/32334054?v=4","gravatar_id":"","url":"https://api.github.com/users/HolyZheng","html_url":"https://github.com/HolyZheng","followers_url":"https://api.github.com/users/HolyZheng/followers","following_url":"https://api.github.com/users/HolyZheng/following{/other_user}","gists_url":"https://api.github.com/users/HolyZheng/gists{/gist_id}","starred_url":"https://api.github.com/users/HolyZheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HolyZheng/subscriptions","organizations_url":"https://api.github.com/users/HolyZheng/orgs","repos_url":"https://api.github.com/users/HolyZheng/repos","events_url":"https://api.github.com/users/HolyZheng/events{/privacy}","received_events_url":"https://api.github.com/users/HolyZheng/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-06-18T15:41:09Z","updated_at":"2018-08-03T06:45:28Z","closed_at":null,"author_association":"OWNER","body":"作者：holyZheng\r\n转载请注明出处\r\n\r\n### iterators（迭代器）\r\n> An iterator is an object with a next method that returns { done, value } tuples.\r\n\r\n定义就是：一个具有next()方法且该方法返回一个 {done， value}元组的对象，done表示是否遍历完，value表示这次遍历的成员值。原生具有iterator接口的数据结构有 String, Array, TypedArray, Map, 和 Set。\r\n\r\n### for-of 循环\r\nfor-of循环与iterator一起工作，会调用数据结构的next()方法，取得返回对象{done, value}的value值，当返回对象{done, value}的done的值为true时停止迭代。\r\n```js\r\nconst arr = [1, 2, 3, 4, 5];\r\nfor (let item of arr) {\r\n  console.log(item); // 1\r\n                     // 2\r\n                     // 3\r\n                     // 4\r\n                     // 5\r\n}\r\n```\r\n在for-of中我们可以使用**break**，**continue**和**return**\r\n```js\r\nconst arr = [1, 2, 3, 4, 5];\r\nfor (let item of arr) {\r\n  if (item > 4) {\r\n    break;\r\n  }\r\n  if (0 !== item % 2) {\r\n    continue;\r\n  }\r\n  console.log(item); // 2\r\n                     // 4\r\n}\r\n```\r\n### Generators\r\ngenerators 是 iterators 的一个子类，它是一个特殊的函数，可以停止和从停止的地方重新开始，generator 采用 function* 和 yield 操作符来实现它的功能。\r\n- 使用function* 运算符来实例化一个generator实例\r\n- yield运算符，作为暂停的标记，返回跟在后面的表达式的值。\r\n- 调用next()方法按顺序执行每段代码，并返回一个对象{value，done}，value为yield运算符后面表达式的值，done表示是否已执行完了所以的代码\r\n```js\r\nfunction* generator () {\r\n  yield 1; \r\n  // pause\r\n  yield 2; \r\n  // pause\r\n  yield 3; \r\n  // pause\r\n  yield 'done?'; \r\n  // done\r\n}\r\nlet gen = generator(); // [object Generator]\r\nconsole.log(gen.next()); // Object {value: 1, done: false}\r\nconsole.log(gen.next()); // Object {value: 2, done: false}\r\nconsole.log(gen.next()); // Object {value: 3, done: false}\r\nconsole.log(gen.next()); // Object {value: 'done?', done: false}\r\nconsole.log(gen.next()); // Object {value: undefined, done: true}\r\nconsole.log(gen.next()); // Object {value: undefined, done: true}\r\nfor (let val of generator()) {\r\n  console.log(val); // 1\r\n                    // 2\r\n                    // 3\r\n                    // 'done?'\r\n}\r\n```\r\n\r\n### 应用：异步操作同步化表达\r\n```js\r\nvar fetch = require('node-fetch');\r\n\r\nfunction* gen(){\r\n  var url = 'https://api.github.com/users/github';\r\n  var result = yield fetch(url);\r\n  console.log(result.bio);\r\n}\r\n\r\nvar g = gen();\r\nvar result = g.next();\r\n\r\nresult.value.then(function(data){\r\n  return data.json();\r\n}).then(function(data){\r\n  g.next(data);\r\n});\r\n```\r\n让其自动自行的其中一个方案：\r\n- Promise 对象。将异步操作包装成 Promise 对象，用then方法交回执行权。\r\n```js\r\nfunction run(gen){\r\n  var g = gen();\r\n\r\n  function next(data){\r\n    var result = g.next(data);\r\n    if (result.done) return result.value;\r\n    result.value.then(function(data){\r\n      next(data);\r\n    });\r\n  }\r\n\r\n  next();\r\n}\r\n\r\nrun(gen);\r\n```\r\n让其自动执行的另一个方案： \r\n- Thunk函数，thunk函数就是只接受一个参数，并且该参数为回调函数，在回调中把执行权交回给generator。\r\n```js\r\nvar fs = require('fs');\r\nvar thunkify = require('thunkify');\r\nvar readFileThunk = thunkify(fs.readFile);\r\n\r\nvar gen = function* (){\r\n  var r1 = yield readFileThunk('/etc/fstab');\r\n  console.log(r1.toString());\r\n};\r\n\r\nvar g = gen();\r\n\r\nvar r1 = g.next();\r\nr1.value(function (err, data) {\r\n  if (err) throw err;\r\n  g.next(data);\r\n});\r\n```\r\n\r\n### co模块\r\n可以让我们的generator自动执行，**原理**是：当异步操作有了结果，就把执行权交回给generator让它继续往下执行。co模块底层就是在thunk函数的回调中或在promise的then方法中，将执行权回交给generator。所以在使用co模块的时候，yield运算符后面得表达式必须返回一个thunk函数或promise对象。\r\n```js\r\nvar co = require('co');\r\nco(gen).then(function (){\r\n  console.log('Generator 函数执行完成');\r\n});;\r\n```"},"comment":{"url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/comments/410160906","html_url":"https://github.com/HolyZheng/holyZheng-blog/issues/7#issuecomment-410160906","issue_url":"https://api.github.com/repos/HolyZheng/holyZheng-blog/issues/7","id":410160906,"node_id":"MDEyOklzc3VlQ29tbWVudDQxMDE2MDkwNg==","user":{"login":"HolyZheng","id":32334054,"node_id":"MDQ6VXNlcjMyMzM0MDU0","avatar_url":"https://avatars2.githubusercontent.com/u/32334054?v=4","gravatar_id":"","url":"https://api.github.com/users/HolyZheng","html_url":"https://github.com/HolyZheng","followers_url":"https://api.github.com/users/HolyZheng/followers","following_url":"https://api.github.com/users/HolyZheng/following{/other_user}","gists_url":"https://api.github.com/users/HolyZheng/gists{/gist_id}","starred_url":"https://api.github.com/users/HolyZheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HolyZheng/subscriptions","organizations_url":"https://api.github.com/users/HolyZheng/orgs","repos_url":"https://api.github.com/users/HolyZheng/repos","events_url":"https://api.github.com/users/HolyZheng/events{/privacy}","received_events_url":"https://api.github.com/users/HolyZheng/received_events","type":"User","site_admin":false},"created_at":"2018-08-03T06:45:28Z","updated_at":"2018-08-03T06:45:28Z","author_association":"OWNER","body":"## async/ await\r\nasync和await可以让我们更加简单得处理异步操作，通过跟promise配合，我们可以完全像处理同步操作一样处理异步操作。\r\n- 通过在function前面添加async关键字来声明一个异步函数，通过await来获取异步操作成功时promise中resolve获得的值。\r\n- 通过try...catch...语句捕获异步操作失败时的错误。\r\n```js\r\nasync function myFunction() {\r\n  try {\r\n    await somethingThatReturnsAPromise();\r\n  } catch (err) {\r\n    console.log(err);\r\n  }\r\n}\r\n```\r\n\r\n注意事项，如果多个异步操作之间没有先后关系，我们应该通过promise.all([promiseA, promiseB, promiseC])来并行的执行它们。\r\n```js\r\nlet [foo, bar] = await Promise.all([getFoo(), getBar()]);\r\n```"}}
{"actor":{"display_login":"HolyZheng"}}