理解 ES6 Generator-next()方法
阿新 • • 發佈:2018-05-24
lB users meta lba content node failed fail class
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. 72 * 1.1 next(param) 方法的參數 param 表示上一條含 yield 關鍵字的語句的返回值 73 (即: 本條含有 yield 關鍵字的整條語句(可能還含有其他變量或表達式)的最終返回值為下一個 next() 中的參數), 所以例1 中: result = data; 74 1.2 或者說: 一條含有 yield 關鍵字的表達式語句(如例-1: let result = yield myAjax(url, ‘get‘, null, successCallBack, failCallBack);), 75 最終的值(result), 等於下一個next(data) 方法中的參數 data; 76 * 2. 註意, gn.next() 返回的是一個對象, 其中的 value 屬性的值等於其剛執行完的含 yield 關鍵字的語句 yield 後面的表達式的結果, 77 如果這個表達式是同步操作, 那返回的對象中 value 立馬有值, 如果是異步操作, 則 value 首先是 undefined, 異步執行完後才有值. 78 * 3. 執行的代碼順序: 調用第一個 next() 執行 mark_1 ~ mark_2 之間的代碼, 79 第二個 next() 執行的是 mark_2 ~ mark_3 之間的代碼, 以此類推; 80 * 4. 例-2 作為參考, 摘自《ES6 標準入門(第3版)》阮一峰 著 第 360 頁內容. 81 * 82 */ 83 84 85 } 86 87 // ------------ function ------------- 88 89 90 // 自定義 ajax, 類型僅限於 get 和 post, 回調函數: success/error 91 function myAjax(url, type, params, success, error) { 92 var xhr = null; 93 var args = null; 94 xhr = new XMLHttpRequest(); 95 xhr.onreadystatechange = function() { 96 if (xhr.readyState == 4) { 97 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { 98 success(xhr.responseText); 99 } else { 100 error("Request was unsuccessful: "+ xhr.status); 101 } 102 } 103 }; 104 xhr.open(type, url, true); // 類型, 連接, 是否異步 105 if (type.toLowerCase() == ‘post‘) { 106 // xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // 默認的表單提交 107 xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8"); // JSON.stringify 處理後的json 鍵值對 108 args = params; 109 } 110 xhr.send(args); 111 } 112 113 </script> 114 115 116 </body> 117 </html>
理解 ES6 Generator-next()方法