摘要:大約后輸出我們直接在官網(wǎng)的粘貼上述代碼,然后查看代碼編譯成什么樣子相關(guān)的代碼我們在系列之將編譯成了什么樣子中已經(jīng)介紹過了,這次我們重點來看看函數(shù)以上這段代碼主要是用來實現(xiàn)的自動執(zhí)行以及返回。
前言
本文就是簡單介紹下 Async 語法編譯后的代碼。
Asyncconst fetchData = (data) => new Promise((resolve) => setTimeout(resolve, 1000, data + 1)) const fetchValue = async function () { var value1 = await fetchData(1); var value2 = await fetchData(value1); var value3 = await fetchData(value2); console.log(value3) }; fetchValue(); // 大約 3s 后輸出 4Babel
我們直接在 Babel 官網(wǎng)的 Try it out 粘貼上述代碼,然后查看代碼編譯成什么樣子:
"use strict"; function _asyncToGenerator(fn) { return function() { var gen = fn.apply(this, arguments); return new Promise(function(resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then( function(value) { step("next", value); }, function(err) { step("throw", err); } ); } } return step("next"); }); }; } var fetchData = function fetchData(data) { return new Promise(function(resolve) { return setTimeout(resolve, 1000, data + 1); }); }; var fetchValue = (function() { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee() { var value1, value2, value3; return regeneratorRuntime.wrap( function _callee$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: _context.next = 2; return fetchData(1); case 2: value1 = _context.sent; _context.next = 5; return fetchData(value1); case 5: value2 = _context.sent; _context.next = 8; return fetchData(value2); case 8: value3 = _context.sent; console.log(value3); case 10: case "end": return _context.stop(); } } }, _callee, this ); }) ); return function fetchValue() { return _ref.apply(this, arguments); }; })(); fetchValue();_asyncToGenerator
regeneratorRuntime 相關(guān)的代碼我們在 《ES6 系列之 Babel 將 Generator 編譯成了什么樣子》 中已經(jīng)介紹過了,這次我們重點來看看 _asyncToGenerator 函數(shù):
function _asyncToGenerator(fn) { return function() { var gen = fn.apply(this, arguments); return new Promise(function(resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then( function(value) { step("next", value); }, function(err) { step("throw", err); } ); } } return step("next"); }); }; }
以上這段代碼主要是用來實現(xiàn) generator 的自動執(zhí)行以及返回 Promise。
當(dāng)我們執(zhí)行 fetchValue() 的時候,執(zhí)行的其實就是 _asyncToGenerator 返回的這個匿名函數(shù),在匿名函數(shù)中,我們執(zhí)行了
var gen = fn.apply(this, arguments);
這一步就相當(dāng)于執(zhí)行 Generator 函數(shù),舉個例子:
function* helloWorldGenerator() { yield "hello"; yield "world"; return "ending"; } var hw = helloWorldGenerator();
var gen = fn.apply(this, arguments) 就相當(dāng)于 var hw = helloWorldGenerator();,返回的 gen 是一個具有 next()、throw()、return() 方法的對象。
然后我們返回了一個 Promise 對象,在 Promise 中,我們執(zhí)行了 step("next"),step 函數(shù)中會執(zhí)行:
try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; }
step("next") 就相當(dāng)于 var info = gen.next(),返回的 info 對象是一個具有 value 和 done 屬性的對象:
{value: Promise, done: false}
接下來又會執(zhí)行:
if (info.done) { resolve(value); } else { return Promise.resolve(value).then( function(value) { step("next", value); }, function(err) { step("throw", err); } ); }
value 此時是一個 Promise,Promise.resolve(value) 依然會返回這個 Promise,我們給這個 Promise 添加了一個 then 函數(shù),用于在 Promise 有結(jié)果時執(zhí)行,有結(jié)果時又會執(zhí)行 step("next", value),從而使得 Generator 繼續(xù)執(zhí)行,直到 info.done 為 true,才會 resolve(value)。
不完整但可用的代碼(function() { var ContinueSentinel = {}; var mark = function(genFun) { var generator = Object.create({ next: function(arg) { return this._invoke("next", arg); } }); genFun.prototype = generator; return genFun; }; function wrap(innerFn, outerFn, self) { var generator = Object.create(outerFn.prototype); var context = { done: false, method: "next", next: 0, prev: 0, sent: undefined, abrupt: function(type, arg) { var record = {}; record.type = type; record.arg = arg; return this.complete(record); }, complete: function(record, afterLoc) { if (record.type === "return") { this.rval = this.arg = record.arg; this.method = "return"; this.next = "end"; } return ContinueSentinel; }, stop: function() { this.done = true; return this.rval; } }; generator._invoke = makeInvokeMethod(innerFn, context); return generator; } function makeInvokeMethod(innerFn, context) { var state = "start"; return function invoke(method, arg) { if (state === "completed") { return { value: undefined, done: true }; } context.method = method; context.arg = arg; while (true) { state = "executing"; if (context.method === "next") { context.sent = context._sent = context.arg; } var record = { type: "normal", arg: innerFn.call(self, context) }; if (record.type === "normal") { state = context.done ? "completed" : "yield"; if (record.arg === ContinueSentinel) { continue; } return { value: record.arg, done: context.done }; } } }; } window.regeneratorRuntime = {}; regeneratorRuntime.wrap = wrap; regeneratorRuntime.mark = mark; })(); "use strict"; function _asyncToGenerator(fn) { return function() { var gen = fn.apply(this, arguments); return new Promise(function(resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then( function(value) { step("next", value); }, function(err) { step("throw", err); } ); } } return step("next"); }); }; } var fetchData = function fetchData(data) { return new Promise(function(resolve) { return setTimeout(resolve, 1000, data + 1); }); }; var fetchValue = (function() { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee() { var value1, value2, value3; return regeneratorRuntime.wrap( function _callee$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: _context.next = 2; return fetchData(1); case 2: value1 = _context.sent; _context.next = 5; return fetchData(value1); case 5: value2 = _context.sent; _context.next = 8; return fetchData(value2); case 8: value3 = _context.sent; console.log(value3); case 10: case "end": return _context.stop(); } } }, _callee, this ); }) ); return function fetchValue() { return _ref.apply(this, arguments); }; })(); fetchValue();
請原諒我水了一篇文章……
ES6 系列ES6 系列目錄地址:https://github.com/mqyqingfeng/Blog
ES6 系列預(yù)計寫二十篇左右,旨在加深 ES6 部分知識點的理解,重點講解塊級作用域、標(biāo)簽?zāi)0濉⒓^函數(shù)、Symbol、Set、Map 以及 Promise 的模擬實現(xiàn)、模塊加載方案、異步處理等內(nèi)容。
如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對作者也是一種鼓勵。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98892.html
摘要:前言本文就是簡單介紹下語法編譯后的代碼。如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎,對作者也是一種鼓勵。 前言 本文就是簡單介紹下 Generator 語法編譯后的代碼。 Generator function* helloWorldGenerator() { yield hello; yield world; return ending...
摘要:上集回顧從零開始手把手教你實現(xiàn)一個一上一集我們介紹了什么是,為什么要用,以及我們要怎樣來實現(xiàn)一個。完成后,在命令行中輸入安裝下依賴。最后返回這個目標(biāo)節(jié)點。明天,我們迎接挑戰(zhàn),開始處理數(shù)據(jù)變動引起的重新渲染,我們要如何新舊,生成補丁,修改。 上集回顧 從零開始手把手教你實現(xiàn)一個Virtual DOM(一)上一集我們介紹了什么是VDOM,為什么要用VDOM,以及我們要怎樣來實現(xiàn)一個VDOM...
摘要:塊級作用域存在于函數(shù)內(nèi)部塊中字符和之間的區(qū)域和塊級聲明用于聲明在指定塊的作用域之外無法訪問的變量。和都是塊級聲明的一種。值得一提的是聲明不允許修改綁定,但允許修改值。這意味著當(dāng)用聲明對象時沒有問題報錯臨時死區(qū)臨時死區(qū),簡寫為。 塊級作用域的出現(xiàn) 通過 var 聲明的變量存在變量提升的特性: if (condition) { var value = 1; } console.lo...
摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。這在語法上,稱為暫時性死區(qū),簡稱。這表明函數(shù)內(nèi)部的變量與循環(huán)變量不在同一個作用域,有各自單獨的作用域。系列文章系列文章地址 showImg(https://segmentfault.com/img/bVbrjjC); 為什么需要塊級作用域 ES5 只有全局作用域和函數(shù)作用域,沒有塊級作用域,這帶來很多不合...
摘要:簡單的說就是,新語法編譯器舊語法。說明所以,對于新特性,我們可以通過使用,也可以通過語法轉(zhuǎn)化來達(dá)到兼容。 0x001 polyfill 我們都知道,js總是一直存在著兼容性問題,雖然其他語言也存在著兼容性問題,比如c++、java,但那種兼容性是新特性在舊版本上的不兼容,js則存在著各種奇形怪哉的不兼容。這其中有著非常復(fù)雜的歷史和時代的原因,并不加以累述。而解決兼容性問題的方法在以前只...
閱讀 2351·2021-11-24 11:16
閱讀 2038·2021-09-30 09:47
閱讀 2006·2021-09-10 10:51
閱讀 1323·2019-08-30 14:08
閱讀 3141·2019-08-30 13:47
閱讀 1529·2019-08-30 13:02
閱讀 3233·2019-08-29 12:29
閱讀 3199·2019-08-26 17:05