1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>generator-next</title>
6 </head>
7 <body>
8
9 <h3>理解 ES6 Generator-next() 方法</h3>
10
11 <script>
12 window.onload = function() {
13 // Generator 异步任务封装
14
15 // 例-1
16 function* gene() {
17 // mark_1
18 let url = 'https://api.github.com/';
19 let result = yield myAjax(url, 'get', null, successCallBack, failCallBack);
20 // mark_2
21 let jsRelt = JSON.parse(result);
22 console.log('调用第二个 next 后, result 才等于 data: ', jsRelt['current_user_url']);
23 yield 'end';
24 // mark_3
25 }
26
27 let gn = gene(); // 返回一个遍历器对象 gn
28 let first_next = gn.next(); // 调用第一个 next 方法: 启动遍历器, 执行 mark_1 ~ mark_2 之间的代码
29 console.log('调用第一个 next 后: ', first_next); // 因为异步, first-next: {value: undefined, done: false}
30
31 // ajax 成功的回调函数
32 function successCallBack(data) {
33 console.log('request-successful: !'/*, data*/);
34 // * relt = gn.next(data) 说明:
35 // * 1. 此处调用第二个 next 方法: 执行 mark_2 ~ mark_3 之间的代码, 返回的对象 relt = {value: "end", done: false}
36 // * 2. yield 'end'; 是同步操作, 所以调用第二个 next 方法后 relt.value 马上等于 yield 后面表达式的结果("end"),
37 // * 不信注释掉第三个 gn.next() 看结果),
38 // * 如果 yield 后面跟的是异步操作, 则需调用下一个 next 方法 relt.value 才有值.
39 let relt = gn.next(data);
40
41 console.log('同步操作, relt 立马有值: ', relt);
42
43 // 已经遍历完所有的 yield 语句, 无论再调用多少个 next() 方法都返回 {value: undefined, done: true}
44 console.log('调用第三个 next 返回的对象: ', gn.next() /*第三个next()方法*/);
45 }
46 // ajax 失败的回调函数
47 function failCallBack(err) {
48 console.log('request-failed: ', err);
49 }
50
51 /*
52 // 例-2
53 var fetch = require('node-fetch');
54 function* gen() {
55 var url = 'https://api.github.com/users/github';
56 var result = yield fetch(url);
57 console.log(result.bio);
58 }
59 // 执行这段代码的方法如下:
60 var g = gen();
61 var result = g.next();
62 result.value.then(function(data) {
63 return data.json();
64 }).then(function(data) {
65 g.next(data);
66 });
67 */
68
69 /*
70 * Generator-next() 总说明:
71 * 1. 按照 《ES6 标准入门(第3版)》阮一峰 著 第 323 页内容,总结 next() 方法。
72 * 1.1 next(param) 方法的参数 param 表示上一条含 yield 关键字的语句中,yield 后面表达式的结果,
73 例-1 中,第一条含 yield 关键字的语句中因为没有其他表达式组合成更复杂的表达式了,所以 myAjax(...args) 中返回的 data 就等于 result;
74 * 2. 注意, gn.next() 返回的是一个对象, 其中的 value 属性的值等于其刚执行完的含 yield 关键字的语句 yield 后面的表达式的结果,
75 如果这个表达式是同步操作, 那返回的对象中 value 立马有值, 如果是异步操作, 则 value 首先是 undefined, 异步执行完后才有值.
76 * 3. 执行的代码顺序: 调用第一个 next() 执行 mark_1 ~ mark_2 之间的代码,
77 第二个 next() 执行的是 mark_2 ~ mark_3 之间的代码, 以此类推;
78 * 4. 例-2 作为参考, 摘自《ES6 标准入门(第3版)》阮一峰 著 第 360 页内容.
79 *
80 */
81
82
83 }
84
85 // ------------ function -------------
86
87
88 // 自定义 ajax, 类型仅限于 get 和 post, 回调函数: success/error
89 function myAjax(url, type, params, success, error) {
90 var xhr = null;
91 var args = null;
92 xhr = new XMLHttpRequest();
93 xhr.onreadystatechange = function() {
94 if (xhr.readyState == 4) {
95 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
96 success(xhr.responseText);
97 } else {
98 error("Request was unsuccessful: "+ xhr.status);
99 }
100 }
101 };
102 xhr.open(type, url, true); // 类型, 连接, 是否异步
103 if (type.toLowerCase() == 'post') {
104 // xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 默认的表单提交
105 xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8"); // JSON.stringify 处理后的json 键值对
106 args = params;
107 }
108 xhr.send(args);
109 }
110
111 </script>
112
113
114 </body>
115 </html>