成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Generator:JS執(zhí)行權(quán)的真實(shí)操作者

YanceyOfficial / 927人閱讀

摘要:執(zhí)行權(quán)由此單向穩(wěn)定的在不同函數(shù)中切換。調(diào)用函數(shù)后,引擎會(huì)為其開辟一個(gè)獨(dú)立的函數(shù)執(zhí)行棧以下簡(jiǎn)稱棧。執(zhí)行權(quán)再次回到外部。成功執(zhí)行完函數(shù),則改變的狀態(tài)為成功。執(zhí)行函數(shù)返回的遍歷器對(duì)象會(huì)繼承函數(shù)的原型對(duì)象。遇到下一個(gè)斷點(diǎn),交出執(zhí)行權(quán)傳出返回值。

前言

ES6提供了一種新型的異步編程解決方案:Generator函數(shù)(以下簡(jiǎn)稱G函數(shù))。它不是使用JS現(xiàn)有能力按照一定標(biāo)準(zhǔn)制定出來的東西(Promise是如此出生的),而是具有新型底層操作能力,與傳統(tǒng)編程完全不同,代表一種新編程邏輯的高大存在。簡(jiǎn)潔方便、受人喜愛的async函數(shù)就是以它為基礎(chǔ)實(shí)現(xiàn)的。

1 意義

JS引擎是單線程的,只有一個(gè)函數(shù)執(zhí)行棧。
當(dāng)當(dāng)前函數(shù)執(zhí)行完后,執(zhí)行棧將其彈出,銷毀包含其局部變量的??臻g,并開始執(zhí)行前一個(gè)函數(shù)。執(zhí)行權(quán)由此單向穩(wěn)定的在不同函數(shù)中切換。雖然Web Worker的出現(xiàn)使我們能夠自行創(chuàng)建多個(gè)線程,但這離靈活的控制:暫停執(zhí)行、切換執(zhí)行權(quán)和中間的數(shù)據(jù)交換等等,還是很有距離的。

G函數(shù)的意義在于,它可以在單線程的背景下,使執(zhí)行權(quán)與數(shù)據(jù)自由的游走于多個(gè)執(zhí)行棧之間,實(shí)現(xiàn)協(xié)程式編程。
調(diào)用G函數(shù)后,引擎會(huì)為其開辟一個(gè)獨(dú)立的函數(shù)執(zhí)行棧(以下簡(jiǎn)稱G棧)。在執(zhí)行它的過程中,可以控制暫停執(zhí)行,并將執(zhí)行權(quán)轉(zhuǎn)出給主執(zhí)行?;蛄硪粋€(gè)G棧(棧在這里可理解為函數(shù))。而此G棧不會(huì)被銷毀而是被凍結(jié),當(dāng)執(zhí)行權(quán)再次回來時(shí),會(huì)在與上次退出時(shí)完全相同的條件下繼續(xù)執(zhí)行。

下面是一個(gè)簡(jiǎn)單的交出和再次獲得執(zhí)行權(quán)的例子。

// 依次打印出:1 2 3 4 5。

let g = G();

console.log("1"); // 執(zhí)行權(quán)在外部。
g.next(); // 開始執(zhí)行G函數(shù),遇到 yield 命令后停止執(zhí)行返回執(zhí)行權(quán)。
console.log("3"); // 執(zhí)行權(quán)再次回到外部。
g.next(); // 再次進(jìn)入到G函數(shù)中,從上次停止的地方開始執(zhí)行,到最后自動(dòng)返回執(zhí)行權(quán)。
console.log("5");

function* G() {
  let n = 4;
  console.log("2");
  yield; // 遇到此命令,會(huì)暫停執(zhí)行并返回執(zhí)行權(quán)。
  console.log(n);
}
2 登堂 2.1 形式

G函數(shù)也是函數(shù),所以具有普通函數(shù)該有的性質(zhì),不過形式上有兩點(diǎn)不同。一是在function關(guān)鍵字和函數(shù)名之間有一個(gè)*號(hào),表示此為G函數(shù)。二是只有在G函數(shù)里才能使用yield命令(以及yield*命令),處于其內(nèi)部的非G函數(shù)也不行。由于箭頭函數(shù)不能使用yield命令,因此不能用作于Generator函數(shù)(可以用作于async函數(shù))。

以下是它的幾種定義方式。

// 聲明式
function* G() {}

// 表達(dá)式
let G = function* () {};

// 作為對(duì)象屬性
let o = {
  G: function* () {}
};

// 作為對(duì)象屬性的簡(jiǎn)寫式
let o = {
  * G() {}
};

// 箭頭函數(shù)不能用作G函數(shù),報(bào)錯(cuò)!
let o = {
  G: *() => {}
};

// 箭頭函數(shù)可以用作 async 函數(shù)。
let o = {
  G: async () => {}
};
2.2 執(zhí)行

調(diào)用普通函數(shù)會(huì)直接執(zhí)行函數(shù)體中的代碼,之后返回函數(shù)的返回值。但G函數(shù)不同,執(zhí)行它會(huì)返回一個(gè)遍歷器對(duì)象(此對(duì)象與數(shù)組中的遍歷器對(duì)象相同),不會(huì)執(zhí)行函數(shù)體內(nèi)的代碼。只有當(dāng)調(diào)用它的next方法(也可能是其它實(shí)例方法)時(shí),才開始了真正執(zhí)行。

在G函數(shù)的執(zhí)行過程中,碰到yieldreturn命令時(shí)會(huì)停止執(zhí)行并將執(zhí)行權(quán)返回。當(dāng)然,執(zhí)行到此函數(shù)末尾時(shí)自然會(huì)返回執(zhí)行權(quán)。每次返回執(zhí)行權(quán)之后再次調(diào)用它的next方法(也可能是其它實(shí)例方法),會(huì)重新獲得執(zhí)行權(quán),并從上次停止的地方繼續(xù)執(zhí)行,直到下一個(gè)停止點(diǎn)或結(jié)束。

// 示例一
let g = G();
g.next(); // 打印出 1
g.next(); // 打印出 2
g.next(); // 打印出 3

function* G() {
  console.log(1);
  yield;
  console.log(2);
  yield;
  console.log(3);
}

// 示例二
let gg = GG();

gg.next(); // 打印出 1
gg.next(); // 打印出 2
gg.next(); // 沒有打印

function* GG() {
  console.log(1);
  yield;
  console.log(2);
  return;
  yield;
  console.log(3);
}
3 入室 3.1 數(shù)據(jù)交互

數(shù)據(jù)如果不能在執(zhí)行權(quán)的更替中取得交互,其存在的意義就會(huì)大打折扣。

G函數(shù)的數(shù)據(jù)輸出和輸入是通過yield命令和next方法實(shí)現(xiàn)的。
yieldreturn一樣,后面可以跟上任意數(shù)據(jù),程序執(zhí)行到此會(huì)交出控制權(quán)并返回其后的跟隨值(沒有則為undefined),作為數(shù)據(jù)的輸出。每次調(diào)用next方法將控制權(quán)移交給G函數(shù)時(shí),可以傳入任意數(shù)據(jù),該數(shù)據(jù)會(huì)等同替換G函數(shù)內(nèi)部相應(yīng)的yield xxx表達(dá)式,作為數(shù)據(jù)的輸入。

執(zhí)行G函數(shù),返回的是一個(gè)遍歷器對(duì)象。每次調(diào)用它的next方法,會(huì)得到一個(gè)具有valuedone字段的對(duì)象。value存儲(chǔ)了移出控制權(quán)時(shí)輸出的數(shù)據(jù)(即yieldreturn后的跟隨值),done為布爾值代表該G函數(shù)是否已經(jīng)完成執(zhí)行。作為遍歷器對(duì)象的它具有和數(shù)組遍歷器相同的其它性質(zhì)。

// n1 的 value 為 10,a 和 n2 的 value 為 100。
let g = G(10);

let n1 = g.next(); // 得到 n 值。
let n2 = g.next(100); // 相當(dāng)將 yield n 替換成 100。

function* G(n) {
  let a = yield n; // let a = 100;
  console.log(a); // 100
  return a;
}

實(shí)際上,G函數(shù)是實(shí)現(xiàn)遍歷器接口最簡(jiǎn)單的途徑,不過有兩點(diǎn)需要注意。一是G函數(shù)中的return語(yǔ)句,雖然通過遍歷器對(duì)象可以獲得return后面的返回值,但此時(shí)done屬性已為true,通過for of循環(huán)是遍歷不到的。二是G函數(shù)可以寫成為永動(dòng)機(jī)的形式,類似服務(wù)器監(jiān)聽并執(zhí)行請(qǐng)求,這時(shí)通過for of遍歷是沒有盡頭的。

--- 示例一:return 返回值。
let g1 = G();
console.log( g1.next() ); // value: 1, done: false
console.log( g1.next() ); // value: 2, done: true
console.log( g1.next() ); // value: undefined, done: true

let g2 = G();
for (let v of g2) {
  console.log(v); // 只打印出 1。
}

function* G() {
  yield 1;
  return 2;
}

--- 示例二:作為遍歷器接口。
let o = {
  id: 1,
  name: 2,
  ago: 3,
  *[Symbol.iterator]() {
    let arr = Object.keys(this);
    for (let v of arr) {
      yield this[v]; // 使用 yield 輸出。
    }
  }
}

for (let v of o) {
  console.log(v); // 依次打印出:1 2 3。
}

--- 示例三:永動(dòng)機(jī)。
let g = G();
g.next(); // 打印出: Do ... 。
g.next(); // 打印出: Do ... 。
// ... 可以無(wú)窮次調(diào)用。

// 可以嘗試此例子,雖然頁(yè)面會(huì)崩潰。
// 崩潰之后可以點(diǎn)擊關(guān)閉頁(yè)面,或終止瀏覽器進(jìn)程,或辱罵作者。
for (let v of G()) {
  console.log(v);
}

function* G() {
  while (true) {
    console.log("Do ...");
    yield;
  }
}
3.2 yield*

yield*命令的基本原理是自動(dòng)遍歷并用yield命令輸出擁有遍歷器接口的對(duì)象,怪繞口的,直接看示例吧。

// G2 與 G22 函數(shù)等價(jià)。

for (let v of G1()) {
  console.log(v); // 打印出:1 [2, 3] 4。
}
for (let v of G2()) {
  console.log(v); // 打印出:1 2 3 4。
}
for (let v of G22()) {
  console.log(v); // 打印出:1 2 3 4。
}

function* G1() {
  yield 1;
  yield [2, 3];
  yield 4;
}

function* G2() {
  yield 1;
  yield* [2, 3]; // 使用 yield* 自動(dòng)遍歷。
  yield 4;
}

function* G22() {
  yield 1;
  for (let v of [2, 3]) { // 等價(jià)于 yield* 命令。
    yield v;
  }
  yield 4;
}

在G函數(shù)中直接調(diào)用另一個(gè)G函數(shù),與在外部調(diào)用沒什么區(qū)別,即便前面加上yield命令。但如果使用yield*命令就能直接整合子G函數(shù)到父函數(shù)中,十分方便。因?yàn)镚函數(shù)返回的就是一個(gè)遍歷器對(duì)象,而yield*可以自動(dòng)展開持有遍歷器接口的對(duì)象,并用yield輸出。如此就等價(jià)于將子G函數(shù)的函數(shù)體原原本本的復(fù)制到父G函數(shù)中。

// G1 與 G2 等價(jià)。

for (let v of G1()) {
  console.log(v); // 依次打印出:1 2 "-" 3 4
}
for (let v of G2()) {
  console.log(v); // 依次打印出:1 2 "-" 3 4
}

function* G1() {
  yield 1;
  yield* GG();
  yield 4;
}

function* G2() {
  yield 1;
  yield 2;
  console.log("-");
  yield 3;
  yield 4;
}

function* GG() {
  yield 2;
  console.log("-");
  yield 3;
}

唯一需要注意的是子G函數(shù)中的return語(yǔ)句。yield*雖然與for of一樣不會(huì)遍歷到該值,但其能直接返回該值。

let g = G();

console.log( g.next().value ); // 1
console.log( g.next().value ); // undefined, 打印出 return 2。

function* G() {
  let n = yield* GG(); // 第二次執(zhí)行 next 方法時(shí),這里等價(jià)于 let n = 2; 。
  console.log("return", n);
}

function* GG() {
  yield 1;
  return 2;
}
3.3 異步應(yīng)用

歷經(jīng)了如此多的鋪墊,是到將其應(yīng)用到異步的時(shí)候了,來來來,喝了這壇酒咱就到馬路上碰個(gè)瓷試試運(yùn)氣。
使用G函數(shù)處理異步的優(yōu)勢(shì),相對(duì)于在這以前最優(yōu)秀的Promise來說,在于形式上使主邏輯代碼更為的精簡(jiǎn)和清晰,使其看起來與同步代碼基本相同。雖然在日常生活中,我們說誰(shuí)誰(shuí)做事愛搞形式多少包含有貶低意味。但在這程序的世界,對(duì)于我們編寫和他人閱讀來說,這些改進(jìn)的效益可是相當(dāng)可觀哦。

// 模擬請(qǐng)求數(shù)據(jù)。
// 依次打印出 get api1, Do ..., get api2, Do ..., 最終值:3000 。

// 請(qǐng)求數(shù)據(jù)的主邏輯塊
function* G() {
  let api1 = yield createPromise(1000); // 發(fā)送第一個(gè)數(shù)據(jù)請(qǐng)求,返回的是該 Promise 。
  console.log("get api1", api1); // 得到數(shù)據(jù)。
  console.log("Do somethings with api1"); // 做些操作。
  
  let api2 = yield createPromise(2000); // 發(fā)送第二個(gè)數(shù)據(jù)請(qǐng)求,返回的是該 Promise 。
  console.log("get api2", api2); // 得到數(shù)據(jù)。
  console.log("Do somethings with api2"); // 做些操作。
  
  return api1 + api2;
}

// 開始執(zhí)行G函數(shù)。
let g = G();
// 得到第一個(gè) Promise 并等待其返回?cái)?shù)據(jù)
g.next().value.then(res => {
  // 獲取到第一個(gè)請(qǐng)求的數(shù)據(jù)。
  return g.next(res).value; // 將第一個(gè)數(shù)據(jù)傳回,并獲取到第二個(gè) Promise 。
}).then(res => {
  // 獲取到第二個(gè)請(qǐng)求的數(shù)據(jù)。
  return g.next(res).value; // 將第二個(gè)數(shù)據(jù)傳回。
}).then(res => {
  console.log("最終值:", res);
});

// 模擬請(qǐng)求數(shù)據(jù)
function createPromise(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(time);
    }, time);
  });
}

上面的方式有很大的優(yōu)化空間。我們執(zhí)行函數(shù)時(shí)的邏輯是:先獲取到異步請(qǐng)求并等待其返回結(jié)果,再將結(jié)果傳遞回G函數(shù),之后重復(fù)操作。而按照此方式,意味著G函數(shù)中有多少異步請(qǐng)求,我們就應(yīng)該重復(fù)多少次該操作。如果觀眾老爺們足夠敏感,此時(shí)就能想到這些步奏是能抽象成一個(gè)函數(shù)的。而抽象出來的這個(gè)函數(shù)就是G函數(shù)的自執(zhí)行器。

以下是一個(gè)簡(jiǎn)易的自執(zhí)行器,它會(huì)返回一個(gè)Promise。再往內(nèi)是通過遞歸一步步的執(zhí)行G函數(shù),對(duì)其返回的結(jié)果都統(tǒng)一使用resolve方法包裝成Promise對(duì)象。

// 與上一個(gè)示例等價(jià)。
RunG(G).then(res => {
  console.log("G函數(shù)執(zhí)行結(jié)束:", res); // 3000
});

function* G() {
  let api1 = yield createPromise(1000);
  console.log("get api1", api1);
  console.log("Do somethings with api1");
  
  let api2 = yield createPromise(2000);
  console.log("get api2", api2);
  console.log("Do somethings with api2");
  
  return api1 + api2;
}

function RunG(G) {
  // 返回 Promise 對(duì)象。
  return new Promise((resolve, reject) => {
    let g = G();

    next();

    function next(data) {
      let r = g.next(data);

      // 成功執(zhí)行完G函數(shù),則改變 Promise 的狀態(tài)為成功。
      if (r.done) return resolve(r.value);

      // 將每次的返回值統(tǒng)一包裝成 Promise 對(duì)象。
      // 成功則繼續(xù)執(zhí)行G函數(shù),否則改變 Promise 的狀態(tài)為失敗。
      Promise.resolve(r.value).then(next).catch(reject);
    }
  });
}

function createPromise(time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(time);
    }, time);
  });
}

自執(zhí)行器可以自動(dòng)執(zhí)行任意的G函數(shù),是應(yīng)用于異步時(shí)必要的咖啡伴侶。上面是接地氣的寫法,我們來看看較為官方的版本??梢灾庇^的感受到,兩者主要的區(qū)別在對(duì)可能錯(cuò)誤的捕獲和處理上,這也是平常寫的代碼和構(gòu)建底層庫(kù)主要的區(qū)別之一。

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}
4 實(shí)例方法

實(shí)例方法比如next以及接下來的throwreturn,實(shí)際是存在G函數(shù)的原型對(duì)象中。執(zhí)行G函數(shù)返回的遍歷器對(duì)象會(huì)繼承G函數(shù)的原型對(duì)象。在此添加自定義方法也可以被繼承。這使得G函數(shù)看起來類似構(gòu)造函數(shù),但實(shí)際兩者不相同。因?yàn)镚函數(shù)本就不是構(gòu)造函數(shù),不能被new,內(nèi)部的this也不能被繼承。

function* G() {
  this.id = 123;
}
G.prototype.sayName = () => {
  console.log("Wmaker");
};

let g = G();
g.id; // undefined
g.sayName(); // "Wmaker"
4.1 throw

實(shí)例方法thrownext方法的性質(zhì)基本相同,區(qū)別在于其是向G函數(shù)體內(nèi)傳遞錯(cuò)誤而不是值。通俗的表達(dá)是將yield xxx表達(dá)式替換成throw 傳入的參數(shù)。其它比如會(huì)接著執(zhí)行到下一個(gè)斷點(diǎn),返回一個(gè)對(duì)象等等,和next方法一致。該方法使得異常處理更為簡(jiǎn)單,而且多個(gè)yield表達(dá)式可以只用一個(gè)try catch代碼塊捕獲。

當(dāng)通過throw方法或G函數(shù)在執(zhí)行中自己拋出錯(cuò)誤時(shí)。如果此代碼正好被try catch塊包裹,便會(huì)像公園里行完方便的寵物一樣,沒事的繼續(xù)往下執(zhí)行。遇到下一個(gè)斷點(diǎn),交出執(zhí)行權(quán)傳出返回值。如果沒有錯(cuò)誤捕獲,JS會(huì)終止執(zhí)行并認(rèn)為函數(shù)已經(jīng)結(jié)束運(yùn)行,此后再調(diào)用next方法會(huì)一直返回valueundefined、donetrue的對(duì)象。

// 依次打印出:1, Error: 2, 3。
let g = G();

console.log( g.next().value ); // 1
console.log( g.throw(2).value ); // 3,打印出 Error: 2。

function* G() {
  try {
    yield 1;
  } catch(e) {
    console.log("Error:", e);
  }
  yield 3;
}

// 使用了 throw(2) 等價(jià)于使用 next() 并將代碼改寫成如下所示。

function* G() {
  try {
    yield 1;
    throw 2; // 替換原來的 yield 表達(dá)式,相當(dāng)在后面添加。
  } catch(e) {
    console.log("Error:", e);
  }
  yield 3;
}
4.2 return

實(shí)例方法returnthrow的情況相同,與next具有相似的性質(zhì)。區(qū)別在于其會(huì)直接終止G函數(shù)的執(zhí)行并返回傳入的參數(shù)。通俗的表達(dá)是將yield xxx表達(dá)式替換成return 傳入的參數(shù)。值得注意的是,如果此時(shí)正好處于try代碼塊中,且其帶有finally模塊,那么return方法會(huì)推遲到finally代碼塊執(zhí)行完后再執(zhí)行。

let g = G();

console.log( g.next().value ); // 1
console.log( g.return(4).value ); // 2
console.log( g.next().value ); // 3
console.log( g.next().value ); // 4,G函數(shù)結(jié)束。
console.log( g.next().value ); // undefined

function* G() {
  try {
    yield 1;
  } finally {
    yield 2;
    yield 3;
  }
  yield 5;
}

// 使用了 return(4) 等價(jià)于使用 next() 并將代碼改寫成如下所示。

function* GG() {
  try {
    yield 1;
    return 4; // 替換原來的 yield 表達(dá)式,相當(dāng)在后面添加。
  } finally {
    yield 2;
    yield 3;
  }
  
  yield 5;
}
延伸

ES6精華:Symbol
ES6精華:Promise
Iterator:訪問數(shù)據(jù)集合的統(tǒng)一接口

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108377.html

相關(guān)文章

  • ES6 Generator實(shí)現(xiàn)協(xié)同程序

    摘要:關(guān)鍵字表示代碼在該處將會(huì)被阻塞式暫停阻塞的僅僅是函數(shù)代碼本身,而不是整個(gè)程序,但是這并沒有引起函數(shù)內(nèi)部自頂向下代碼的絲毫改變。通過實(shí)現(xiàn)模式在通過實(shí)現(xiàn)理論的過程中已經(jīng)有一些有趣的探索了。 至此本系列的四篇文章翻譯完結(jié),查看完整系列請(qǐng)移步blogs 由于個(gè)人能力知識(shí)有限,翻譯過程中難免有紕漏和錯(cuò)誤,望不吝指正issue ES6 Generators: 完整系列 The Basics...

    MudOnTire 評(píng)論0 收藏0
  • 【面試篇】寒冬求職季之你必須要懂原生JS(中)

    摘要:如果你還沒讀過上篇上篇和中篇并無(wú)依賴關(guān)系,您可以讀過本文之后再閱讀上篇,可戳面試篇寒冬求職季之你必須要懂的原生上小姐姐花了近百個(gè)小時(shí)才完成這篇文章,篇幅較長(zhǎng),希望大家閱讀時(shí)多花點(diǎn)耐心,力求真正的掌握相關(guān)知識(shí)點(diǎn)。 互聯(lián)網(wǎng)寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環(huán)境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包,this,原型鏈,就能獲得...

    andycall 評(píng)論0 收藏0
  • 【面試篇】寒冬求職季之你必須要懂原生JS(中)

    摘要:如果你還沒讀過上篇上篇和中篇并無(wú)依賴關(guān)系,您可以讀過本文之后再閱讀上篇,可戳面試篇寒冬求職季之你必須要懂的原生上小姐姐花了近百個(gè)小時(shí)才完成這篇文章,篇幅較長(zhǎng),希望大家閱讀時(shí)多花點(diǎn)耐心,力求真正的掌握相關(guān)知識(shí)點(diǎn)。 互聯(lián)網(wǎng)寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環(huán)境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包,this,原型鏈,就...

    Mike617 評(píng)論0 收藏0
  • Generator 自啟動(dòng)

    摘要:文章同步自個(gè)人博客此前只是簡(jiǎn)單使用而沒有真正的去研究,這次要好好折騰下這貨。我們要實(shí)現(xiàn)一個(gè)啟動(dòng)器來運(yùn)行它,并把結(jié)果傳給下一次,這樣就實(shí)現(xiàn)了接收值的功能。就啟動(dòng)起來了,并且一直執(zhí)行到為為止。如果執(zhí)行不了,請(qǐng)升級(jí)瀏覽器,本例在下通過。 文章同步自個(gè)人博客:http://www.52cik.com/2016/07/11/generator-co.html 此前只是簡(jiǎn)單使用而沒有真正的去研究 ...

    junbaor 評(píng)論0 收藏0
  • 通過ES6 Generator函數(shù)實(shí)現(xiàn)異步流程

    摘要:換句話說,我們很好的對(duì)代碼的功能關(guān)注點(diǎn)進(jìn)行了分離通過將使用消費(fèi)值得地方函數(shù)中的邏輯和通過異步流程來獲取值迭代器的方法進(jìn)行了有效的分離。但是現(xiàn)在我們通過來管理代碼的異步流程部分,我們解決了回調(diào)函數(shù)所帶來的反轉(zhuǎn)控制等問題。 本文翻譯自 Going Async With ES6 Generators 由于個(gè)人能力知識(shí)有限,翻譯過程中難免有紕漏和錯(cuò)誤,還望指正Issue ES6 Gener...

    劉厚水 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<