成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Generator 詳解(使用場景,babel 轉(zhuǎn)譯,協(xié)程,異步,上層應(yīng)用,async/await)

raise_yang / 2707人閱讀

摘要:不需要多線程的鎖機(jī)制線程由系統(tǒng)控制切換,協(xié)程是由用戶控制切換。協(xié)程的中斷實(shí)際上是掛起的概念協(xié)程發(fā)起異步操作意味著該協(xié)程將會被掛起,為了保證喚醒時能正常運(yùn)行,需要正確保存并恢復(fù)其運(yùn)行時的上下文。

博客 github 地址: https://github.com/HCThink/h-blog/blob/master/js/syncAndAsync/generator/readme.md

github 首頁(star+watch,一手動態(tài)直達(dá)): https://github.com/HCThink/h-blog

掘金 link , 掘金 專欄

segmentfault 主頁

原創(chuàng)禁止私自轉(zhuǎn)載

Generator
可以隨心所欲的交出和恢復(fù)函數(shù)的執(zhí)行權(quán),yield交出執(zhí)行權(quán),next()恢復(fù)執(zhí)行權(quán)

Generator 函數(shù)是一個狀態(tài)機(jī),封裝了多個內(nèi)部狀態(tài),執(zhí)行一個Generator函數(shù)會返回一個迭代器對象,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)

調(diào)用一個生成器函數(shù)并不會馬上執(zhí)行它里面的語句,而是返回一個這個 generator 的 迭代器 (iterator )對象。當(dāng)這個迭代器的 next() 方法被首次(后續(xù))調(diào)用時,其內(nèi)的語句會執(zhí)行到第一個(后續(xù))出現(xiàn)yield的位置為止,yield 后緊跟迭代器要返回的值。

或者如果用的是 yield*(多了個星號),則表示將執(zhí)行權(quán)移交給另一個生成器函數(shù)(當(dāng)前生成器暫停執(zhí)行)。

next()方法返回一個對象,這個對象包含兩個屬性:value 和 done,value 屬性表示本次 yield 表達(dá)式的返回值,done 屬性為布爾類型,表示生成器后續(xù)是否還有 yield 語句,即生成器函數(shù)是否已經(jīng)執(zhí)行完畢并返回。

典型場景

co

async/await

依賴 async 的上層庫和應(yīng)用不勝枚舉,比如 koa

koa 等依賴其上層語法糖封裝: koa

基本使用 code

function* 這種聲明方式(function關(guān)鍵字后跟一個星號)會定義一個生成器函數(shù) (generator function),它返回一個 Generator 對象。

更多 demo 參考: 迭代器 , 常見數(shù)列生成器
// 斐波那契豎列生成器
function* fib() {
    let [x, y]: [number, number] = [0, 1];
    while (true) {
      [x, y] = [y, x + y];
      yield x;
    }
}

const generator: Generator = fib();

// 階乘
function* factorial() {
    let x: number = 1;
    let fac: number = 1;
    while (true) {
        yield fac;
        fac = fac * ++x;
    }
}
Generator 對象

調(diào)用一個生成器函數(shù)并不會馬上執(zhí)行它里面的語句,而是返回這個生成器的 迭代器 (實(shí)現(xiàn) iterator )的對象 Generator, 所以它符合可迭代協(xié)議和迭代器協(xié)議。如上述代碼中 const generator: Generator = fib(); 接受 fib() 的類型即: Generator

Generator 對象

Generator.prototype.next()

返回一個由 yield表達(dá)式生成的值。

Generator.prototype.return()

返回給定的值并結(jié)束生成器。

Generator.prototype.throw()

向生成器拋出一個錯誤。
yield 優(yōu)先級

操作符優(yōu)先級匯總

yield 僅僅比 展開運(yùn)算符: ..., 逗號: , 的優(yōu)先級高,所以注意區(qū)分 yield fn() + 10fn() + 10 才是 yield 表達(dá)式。

generator 中斷 的入?yún)⒑头祷?/b>

generator 入?yún)⒎祷?/p>

注意,不是要說整個 generator 的出入?yún)?,而?yield 和 next,這個問題,其實(shí)困擾我蠻久的,原因是 generator 和傳統(tǒng) js 的函數(shù)調(diào)用區(qū)別很大, 如果你很熟悉普通函數(shù)調(diào)用的出入?yún)?在這里往往轉(zhuǎn)不過彎。

返回: next() 返回類 { done: boolean, value: any } 對象, 其中 value 則是 yield 表達(dá)式的值。

實(shí)際上返回會好理解一些,當(dāng)我們執(zhí)行 generator 函數(shù)之后獲得一個 Generator 對象當(dāng)我們第一次調(diào)用 GeneratorObj.next() 時,函數(shù)才會開始執(zhí)行,直到第一個 yield 表達(dá)式執(zhí)行完成, 并將 yield 表達(dá)式結(jié)果提供給 next 進(jìn)行返回?!咀⒁?yield 表達(dá)式此時開始執(zhí)行】,然后進(jìn)入中斷。

function pi(n: number): number {
    return Math.PI * n;
}

function* fn(n: number) {
    // 第一個 next 調(diào)用后 yield 表達(dá)式【pi(n) + 10, 注意優(yōu)先級】執(zhí)行并將結(jié)果: 13.1415... 進(jìn)行包裝
    // { value: 13.14..., done: false }
    let g1 = yield pi(n) + 10;
    // 同理這里就是: { value: 3.141592653589793, done: false }
    g1 = (yield pi(n)) + 10;

    // return 等價一最后一個 yield。
    return 100;
}

const fnGenx: Generator = fn(1);
Log(fnGenx.next());         // { value: 13.141592653589793, done: false }
Log(fnGenx.next());         // { value: 3.141592653589793, done: false }
Log(fnGenx.next());         // { value: 100, done: true }

當(dāng)在生成器函數(shù)中顯式 return 時,會導(dǎo)致生成器立即變?yōu)橥瓿蔂顟B(tài),即調(diào)用 next() 方法返回的對象的 done 為 true。如果 return 后面跟了一個值,那么這個值會作為當(dāng)前調(diào)用 next() 方法返回的 value 值。

調(diào)用 next 時會立即獲得 yield 表達(dá)式的執(zhí)行結(jié)果。也就是說 yield 不能多帶帶處理異步,因為 yield 其實(shí)不在意其后的表達(dá)式所有代碼執(zhí)行結(jié)束的時間點(diǎn)。因此也無法確定下次 next 的調(diào)用時間點(diǎn)。

入?yún)? next 方法也可以通過接受一個參數(shù)用以向生成器傳值。請注意,首次調(diào)用 next 方法時參數(shù)會被丟棄。next 入?yún)⒁?guī)則如下:

調(diào)用 next()方法時,如果傳入了參數(shù),那么這個參數(shù)會作為上一條執(zhí)行的 yield 語句的返回值

實(shí)際上往往會誤認(rèn)為 let g1 = (yield x10(n)) + 10; 中 yield 表達(dá)式的值就會直接賦值給 g1 其實(shí)并不是這樣的,yield 表達(dá)式的值是 next 的返回值,當(dāng)下次 next(100) 傳入的值會替代上一個 yield 表達(dá)式的值。也就等價于 g1 = (100) + 10

function x10(n: number): number {
    return 10 * n;
}

function* fn(n: number) {
    // yield x10(n) + 10 結(jié)果為:30, 下次 next 時傳入的值做了 +10, 則 g1 值為: 40
    let g1 = yield x10(n) + 10;
    Log(g1);            // 40
    // 同理: (yield x10(g1)) 結(jié)果為: 40 * 10 = 400, 下次 next 時傳入的值: 400 + 10 = 410
    // 代入中斷的點(diǎn): g1 = 410(yield x10(g1)) + 10 =  420
    g1 = (yield x10(g1)) + 10;
    Log(g1);            // 420
}

// 第一個參數(shù)由生成器提供
const fnGenx: Generator = fn(2);
let genObj = fnGenx.next(100);    // 第一次入?yún)粊G棄, 因為他沒有上一個 yield

while (!genObj.done) {
    Log("outer: ", genObj.value);
    genObj = fnGenx.next(genObj.value + 10);
}

// outer:  30
// 40
// outer:  400
// 420
一個官方 demo
/** gen函數(shù)運(yùn)行解析:
 * i=0 時傳入?yún)?shù)(0),并將參數(shù)0賦給上一句yield的返回賦值,由于沒有上一句yield語句,這步被忽略
 * 執(zhí)行var val =100,然后執(zhí)行yield val,此時g.next(i)返回{ value: 100, done: false }
 * 然后console.log(i,g.next(i).value),打印出0 100
 *
 * i=1 時傳入?yún)?shù)(1),并將參數(shù)1賦給上一句yield的返回賦值,即(val = 1)
 * 然后執(zhí)行console.log(val),打印出1。
 * 接著進(jìn)入第二次while循環(huán),調(diào)用yield val,此時g.next(i)返回{ value: 1, done: false }
 * 然后console.log(i,g.next(i).value),打印出1 1
 *
 * i=2 ....(省略)
 */
function* gen() {
   var val =100;
   while(true) {
      val = yield val;
      console.log(val);
   }
}

var g = gen();
for(let i =0;i<5;i++){
   console.log(i,g.next(i).value);
}

// 返回:
//  0 100
//  1
//  1 1
//  2
//  2 2
//  3
//  3 3
//  4
//  4 4

yield*

如果 yield* Generator, 可以等價認(rèn)為將 這個 Generator 的所有 yield 插入到 當(dāng)前位置

function* anotherGenerator(i) {
    yield i + 1;
    yield i + 2;
    yield i + 3;
}

function* generator(i){
    yield i;
    yield* anotherGenerator(i);// 移交執(zhí)行權(quán)
    yield i + 10;
}

// 等價于
function* generator(i){
    yield i;
    //   yield* anotherGenerator(i);// 移交執(zhí)行權(quán)
    yield i + 1;
    yield i + 2;
    yield i + 3;
    yield i + 10;
}
注意點(diǎn)

next 的參數(shù)會作為上一條執(zhí)行的 yield 語句的返回值: let first = yield 1; 中 first 不是直接賦值為 yield 表達(dá)式的值, 而是 下次 next 傳入的值。

生成器函數(shù)不能當(dāng)做構(gòu)造器使用。

function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor"

yield 表達(dá)式是立即執(zhí)行的,并且返回表達(dá)式值, 如果 yield 表達(dá)式是異步的,你需要在恰當(dāng)?shù)臅r機(jī)觸發(fā) next 才能達(dá)到 async 的執(zhí)行順序。在『重要問題 generator & 異步』中有詳細(xì)講解

generator 和異步機(jī)制不同,只是配合 generator + 執(zhí)行器可以 "同步化" 處理異步, Generator 函數(shù)是ES6提供的一種異步編程解決方案

“中斷”是 Generator 的重要特征 ———— Generator 能讓一段程序執(zhí)行到指定的位置先中斷,啟動。

babel 轉(zhuǎn)譯

參考: demo

function *gen(p) {
  console.log(p)
  const de1 = yield fn(p);
  console.log(de1)
  const de2 = yield fn(de1);
  console.log(de2)
}

function fn(p) {
    return Math.random() * p;
}

通過 babel 編譯為

"use strict";
var _marked = /*#__PURE__*/regeneratorRuntime.mark(gen);
function gen(p) {
  var de1, de2;
  return regeneratorRuntime.wrap(function gen$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          console.log(p);
          _context.next = 3;
          return fn(p);
        case 3:
          de1 = _context.sent;
          console.log(de1);
          _context.next = 7;
          return fn(de1);
        case 7:
          de2 = _context.sent;
          console.log(de2);
        case 9:
        case "end":
          return _context.stop();
      }
    }
  }, _marked, this);
}

function fn(p) {
  return Math.random() * p;
}

可以看到 babel 使用了一個諸如的對象: regeneratorRuntime 在不支持的環(huán)境 polyfill,這個對象解析出現(xiàn)在 babel 的 babel-plugin-transform-runtime 插件中.

插件目錄

source

const moduleName = injectCoreJS2
    ? "@babel/runtime-corejs2"
    : "@babel/runtime";
let modulePath = moduleName;

if (node.name === "regeneratorRuntime" && useRuntimeRegenerator) {
    path.replaceWith(
    this.addDefaultImport(
        `${modulePath}/regenerator`,
        "regeneratorRuntime",
    ),
    );
    return;
}

繼續(xù)跟進(jìn)到 babel-runtime-corejs2/regenerator/index.js, babel-runtime/regenerator/index.js 文件中, 兩個文件均只有一行代碼: module.exports = require("regenerator-runtime"); 都使用了 fackbook 的 regenerator

regenerator

regenerator 源碼分析參考

支撐思想: 協(xié)程
協(xié)程,又稱微線程,纖程. 是一種非搶占式資源調(diào)度單元, 是一個無優(yōu)先級的輕量級的用戶態(tài)線程
前期知識準(zhǔn)備

現(xiàn)代操作系統(tǒng)是分時操作系統(tǒng),資源分配的基本單位是進(jìn)程,CPU調(diào)度的基本單位是線程。

簡單來說,進(jìn)程(Process), 線程(Thread)的調(diào)度是由操作系統(tǒng)負(fù)責(zé),線程的睡眠、等待、喚醒的時機(jī)是由操作系統(tǒng)控制,開發(fā)者無法精確的控制它們。使用協(xié)程,開發(fā)者可以自行控制程序切換的時機(jī),可以在一個函數(shù)執(zhí)行到一半的時候中斷執(zhí)行,讓出CPU,在需要的時候再回到中斷點(diǎn)繼續(xù)執(zhí)行。

上下文: 指的是程序在執(zhí)行中的一個狀態(tài)。通常我們會用調(diào)用棧來表示這個狀態(tài)——棧記載了每個調(diào)用層級執(zhí)行到哪里,還有執(zhí)行時的環(huán)境情況等所有有關(guān)的信息。

調(diào)度: 指的是決定哪個上下文可以獲得接下去的CPU時間的方法。

進(jìn)程: 是一種古老而典型的上下文系統(tǒng),每個進(jìn)程有獨(dú)立的地址空間,資源句柄,他們互相之間不發(fā)生干擾。

線程: 是一種輕量進(jìn)程,實(shí)際上在linux內(nèi)核中,兩者幾乎沒有差別,除了線程并不產(chǎn)生新的地址空間和資源描述符表,而是復(fù)用父進(jìn)程的。 但是無論如何,線程的調(diào)度和進(jìn)程一樣,必須陷入內(nèi)核態(tài)。

協(xié)程

傳統(tǒng)的編程語言,早有多任務(wù)的解決方案,其中有一種叫做"協(xié)程"(coroutine),意思是多個線程互相協(xié)作,完成異步任務(wù), 這和普通的搶占式線程有所不同。

JS 中 generator 就類似一個語言層面實(shí)現(xiàn)的非搶占式的輕量級"線程"。 線程包含于進(jìn)程,而協(xié)程包含于線程

所以協(xié)程具有極高的執(zhí)行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢就越明顯。

不需要多線程的鎖機(jī)制

線程由系統(tǒng)控制切換,協(xié)程是由用戶控制切換。

從更高的層面來講,協(xié)程和多線程是兩種解決“多任務(wù)”編程的技術(shù)。多線程使得 "同一時刻貌似" 有多個線程在并發(fā)執(zhí)行,不過需要在多個線程間協(xié)調(diào)資源,因為多個線程的執(zhí)行進(jìn)度是“不可控”的。而協(xié)程則避免了多線程的問題,同一時刻實(shí)質(zhì)上只有一個“線程”在執(zhí)行,所以不會存在資源“搶占”的問題。

不過在 JS 領(lǐng)域,貌似不存在技術(shù)選擇的困難,因為 JS 目前還是“單線程”的,所以引入?yún)f(xié)程也是很自然的選擇吧。

協(xié)程 & 函數(shù)棧

大多語言都是層級調(diào)用,比如A調(diào)用B,B在執(zhí)行過程中又調(diào)用了C,C執(zhí)行完畢返回,B執(zhí)行完畢返回,最后是A執(zhí)行完畢。所以子程序調(diào)用是通過棧實(shí)現(xiàn)的,一個線程就是執(zhí)行一個子程序。子程序調(diào)用總是一個入口,一次返回,調(diào)用順序是明確的。

而協(xié)程的調(diào)用和子程序不同。協(xié)程看上去也是子程序,但執(zhí)行過程中,在子程序內(nèi)部可中斷,然后轉(zhuǎn)而執(zhí)行別的子程序,在適當(dāng)?shù)臅r候再返回來接著執(zhí)行。

協(xié)程的中斷: 實(shí)際上是掛起的概念

協(xié)程發(fā)起異步操作意味著該協(xié)程將會被掛起,為了保證喚醒時能正常運(yùn)行,需要正確保存并恢復(fù)其運(yùn)行時的上下文。記錄步驟為:

保存當(dāng)前協(xié)程的上下文(運(yùn)行棧,返回地址,寄存器狀態(tài))

設(shè)置將要喚醒的協(xié)程的入口指令地址到IP寄存器

恢復(fù)將要喚醒的協(xié)程的上下文

可以參考 libco 騰訊開源的一個C++協(xié)程庫,作為微信后臺的基礎(chǔ)庫,經(jīng)受住了實(shí)際的檢驗: libco

JS 協(xié)程: generator

js 的生成器也是一種特殊的協(xié)程,它擁有 yield 原語,但是卻不能指定讓步的協(xié)程,只能讓步給生成器的調(diào)用者或恢復(fù)者。由于不能多個協(xié)程跳來跳去,生成器相對主執(zhí)行線程來說只是一個可暫停的玩具,它甚至都不需要另開新的執(zhí)行棧,只需要在讓步的時候保存一下上下文就好。因此我們認(rèn)為生成器與主控制流的關(guān)系是不對等的,也稱之為非對稱協(xié)程(semi-coroutine)。

因此一般的協(xié)程實(shí)現(xiàn)都會提供兩個重要的操作 Yield 和 Resume(next)。

Generator 實(shí)現(xiàn)協(xié)程的問題

在協(xié)程執(zhí)行中不能有阻塞操作,否則整個線程被阻塞(協(xié)程是語言級別的,線程,進(jìn)程屬于操作系統(tǒng)級別)

需要特別關(guān)注全局變量、對象引用的使用

yield 僅能存在于 生成器內(nèi)部[對比 node-fibers]

真.協(xié)程

所謂的真協(xié)程是相對 generator 而言的, node-fibers 庫提供了對應(yīng)的實(shí)現(xiàn),我們用一個例子部分代碼說明二者區(qū)別

import Fiber from "fibers"
function fibersCo () {    /* 基于 fibers 的執(zhí)行器 ..... */    }
fibersCo(() => {
    let foo1 = a => {
        console.log("read from file1");
        let ret = Fiber.yield(a);
        return ret;
    };
    let foo2 = b => {
        console.log("read from file2");
        let ret = Fiber.yield(b);
        return ret;
    };
    let getSum = () => {
        let f1 = foo1(readFile("/etc/fstab"));
        let f2 = foo2(readFile("/etc/shells"));
        return f1.toString().length + f2.toString().length;
    };

    let sum = getSum();
});

通過這個代碼可以發(fā)現(xiàn),在第一次中斷被恢復(fù)的時候,恢復(fù)的是一系列的執(zhí)行棧!從棧頂?shù)綏5滓来螢椋篺oo1 => getSum => fibersCo 里的匿名函數(shù);而使用生成器,我們就無法寫出這樣的程序,因為 yield 原語只能在生產(chǎn)器內(nèi)部使用, SO

無論什么時候被恢復(fù),都是簡單的恢復(fù)在生成器內(nèi)部,所以說生成器的中斷是不開調(diào)用棧滴。
重要問題 generator & 異步

generator 處理異步

generator 機(jī)制和異步有所不同, Generator 和普通函數(shù)本質(zhì)區(qū)別在于 Generator 能讓一段程序執(zhí)行到指定的位置,然后交出執(zhí)行棧,調(diào)用下次 next 的時候又會從之前中斷的位置繼續(xù)開始執(zhí)行,配合這種機(jī)制處理異步,則會產(chǎn)生同步化異步處理的效果。

generator 的問題

但其實(shí)很快發(fā)現(xiàn) generator 不能多帶帶處理異步問題,原因在于

generator 無法獲取下次 next 的時機(jī)。

generator 無法自執(zhí)行

generator 處理異步的思路 + 實(shí)踐

使用 Generator 函數(shù)來處理異步操作的基本思想就是在執(zhí)行異步操作時暫停生成器函數(shù)的執(zhí)行,然后在階段性異步操作完成的狀態(tài)中通過生成器對象的next方法讓Generator函數(shù)從暫停的位置恢復(fù)執(zhí)行,如此往復(fù)直到生成器函數(shù)執(zhí)行結(jié)束。簡單來講其實(shí)就是將異步串行化了。

也正是基于這種思想,Generator函數(shù)內(nèi)部才得以將一系列異步操作寫成類似同步操作的形式,形式上更加簡潔明了。

而要讓Generator函數(shù)按順序自動完成內(nèi)部定義好的一系列異步操作,還需要配套的執(zhí)行器。與之配套的有兩種思路

thunk

promise

其實(shí)在 async/await 之前就已經(jīng)有了 co 庫使用此兩種方案實(shí)現(xiàn)類似 async 的機(jī)制。參考 co 源碼分析

co 源碼分析

優(yōu)勢: 異常捕獲。 generator 的異常捕獲模型,優(yōu)于 promise。

function* gen(x){
  try {
    var y = yield x + 2;
  } catch (e){
    console.log(e);
  }
  return y;
}
generator 的 yield 會產(chǎn)生調(diào)用函數(shù)棧么?

因為 yield 原語只能在生產(chǎn)器內(nèi)部使用, 所以無論什么時候被恢復(fù),都是簡單的恢復(fù)在生成器內(nèi)部。所以說生成器的中斷是不開調(diào)用棧滴。

參考上述章節(jié)

真.協(xié)程

中斷/函數(shù)棧

上層應(yīng)用

async / await

async / await, co

并發(fā)通信: 多個generator函數(shù)結(jié)合在一起,讓他們獨(dú)立平行的運(yùn)行,并且在它們執(zhí)行的過程中來來回回得傳遞信息

csp : 并行(多個 generator 微線程通訊)

參考

function* api

Generator api

https://cnodejs.org/topic/58d...

https://www.cnblogs.com/wangf...

https://github.com/Jocs/jocs....

https://cnodejs.org/topic/58d...

https://brooch.me/2016/12/30/...

https://blog.csdn.net/shenlei...

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/100012.html

相關(guān)文章

  • js學(xué)習(xí)之異步處理

    摘要:學(xué)習(xí)開發(fā),無論是前端開發(fā)還是都避免不了要接觸異步編程這個問題就和其它大多數(shù)以多線程同步為主的編程語言不同的主要設(shè)計是單線程異步模型。由于異步編程可以實(shí)現(xiàn)非阻塞的調(diào)用效果,引入異步編程自然就是順理成章的事情了。 學(xué)習(xí)js開發(fā),無論是前端開發(fā)還是node.js,都避免不了要接觸異步編程這個問題,就和其它大多數(shù)以多線程同步為主的編程語言不同,js的主要設(shè)計是單線程異步模型。正因為js天生的與...

    VioletJack 評論0 收藏0
  • 記一次小程序開發(fā)中如何使用async-await并封裝公共異步請求

    摘要:實(shí)現(xiàn)方案首先小程序目前還是不支持的和的,那么如何讓它支持呢點(diǎn)擊下載,并把下載好的文件夾放到自己小程序的目錄下,包總共才多,體積很小的。如果想使用這些新的對象和方法,必須使用,為當(dāng)前環(huán)境提供一個墊片。用于實(shí)現(xiàn)瀏覽器并不支持的原生的代碼。 前言 在平常的項目開發(fā)中肯定會遇到同步異步執(zhí)行的問題,還有的就是當(dāng)執(zhí)行某一個操作依賴上一個執(zhí)行所返回的結(jié)果,那么這個時候你會如何解決這個問題呢; 1.是...

    why_rookie 評論0 收藏0
  • JavaScript 與 異步編程

    摘要:然而異步編程真正發(fā)展壯大,的流行功不可沒。于是從異步編程誕生的那一刻起,它就和回調(diào)函數(shù)綁在了一起。這個函數(shù)會起一個定時器,在超過指定時間后執(zhí)行指定的函數(shù)。我們知道是異步編程的未來。 什么是異步(Asynchrony) 按照維基百科上的解釋:獨(dú)立于主控制流之外發(fā)生的事件就叫做異步。比如說有一段順序執(zhí)行的代碼 void function main() { fA(); fB(); }...

    YFan 評論0 收藏0
  • 一篇文章了解前端異步編程方案演變

    摘要:對于而言,異步編程我們可以采用回調(diào)函數(shù),事件監(jiān)聽,發(fā)布訂閱等方案,在之后,又新添了,,的方案??偨Y(jié)本文闡述了從回調(diào)函數(shù)到的演變歷史。參考文檔深入掌握異步編程系列理解的 對于JS而言,異步編程我們可以采用回調(diào)函數(shù),事件監(jiān)聽,發(fā)布訂閱等方案,在ES6之后,又新添了Promise,Genertor,Async/Await的方案。本文將闡述從回調(diào)函數(shù)到Async/Await的演變歷史,以及它們...

    lmxdawn 評論0 收藏0
  • async/await 更好的異步解決方案

    摘要:大家都一直在嘗試使用更好的方案來解決這些問題。這是一個用同步的思維來解決異步問題的方案。當(dāng)我們發(fā)出了請求,并不會等待響應(yīng)結(jié)果,而是會繼續(xù)執(zhí)行后面的代碼,響應(yīng)結(jié)果的處理在之后的事件循環(huán)中解決。我們可以用一個兩人問答的場景來比喻異步與同步。 在實(shí)際開發(fā)中總會遇到許多異步的問題,最常見的場景便是接口請求之后一定要等一段時間才能得到結(jié)果,如果遇到多個接口前后依賴,那么問題就變得復(fù)雜。大家都一直...

    Ali_ 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<