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>