国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Generator和Async/Await

Eastboat / 1234人閱讀

摘要:以往的異步方法無外乎回調(diào)函數(shù)和。出錯了出錯了總結(jié)接口遍歷器對象除了具有方法,還可以具有方法和方法。函數(shù)調(diào)用函數(shù),返回一個遍歷器對象,代表函數(shù)的內(nèi)部指針。

引言

接觸過Ajax請求的會遇到過異步調(diào)用的問題,為了保證調(diào)用順序的正確性,一般我們會在回調(diào)函數(shù)中調(diào)用,也有用到一些新的解決方案如Promise相關(guān)的技術(shù)。

在異步編程中,還有一種常用的解決方案,它就是Generator生成器函數(shù)。顧名思義,它是一個生成器,它也是一個狀態(tài)機(jī),內(nèi)部擁有值及相關(guān)的狀態(tài),生成器返回一個迭代器Iterator對象,我們可以通過這個迭代器,手動地遍歷相關(guān)的值、狀態(tài),保證正確的執(zhí)行順序。

Iterator接口

什么是Iterator接口

遍歷器(Iterator)就是這樣一種機(jī)制。它是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署Iterator接口,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)。

Iterator的作用

為各種數(shù)據(jù)結(jié)構(gòu),提供一個統(tǒng)一的、簡便的訪問接口

使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列

ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator接口主要供for...of消費(fèi)。

Iterator實(shí)現(xiàn)
function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

var it = makeIterator(["a", "b"]);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
原生具備Iterator接口的數(shù)據(jù)結(jié)構(gòu)

Array

Map

Set

String

TypedArray

函數(shù)的 arguments 對象

NodeList 對象

查看一下Map下面的所掛載的Iterator

let map = new Map();
console.log(map.__proto__);

輸出結(jié)果:

clear:? clear()
constructor:? Map()
delete:? delete()
entries:? entries()
forEach:? forEach()
get:? ()
has:? has()
keys:? keys()
set:? ()
size:(...)
values:? values()
Symbol(Symbol.iterator):? entries()
Symbol(Symbol.toStringTag):"Map"
get size:? size()
__proto__:Object
如何為Object部署一個Iterator接口
function iteratorObject(obj){
    let keys = Object.keys(obj);
    let index = -1;
    return {
        next(){
            index++;
            return index

通過上面的方法可以簡單的為Object部署了一個Iterator接口。

Generator函數(shù)

Generator是ES6的新特性,通過yield關(guān)鍵字,可以讓函數(shù)的執(zhí)行流掛起,那么便為改變執(zhí)行流程提供了可能。

Generator語法

dome:

function * greneratorDome(){
    yield "Hello";
    yield "World";
    return "ending";
}
let grenDome = greneratorDome();
console.log(grenDome)

上面的代碼中定義了一個Generator函數(shù),獲取到了函數(shù)返回的對象。下面是其輸出結(jié)果。

原型鏈:

greneratorDome {}
__proto__:Generator
    __proto__:Generator
    constructor:GeneratorFunction {prototype: Generator, constructor: ?, Symbol(Symbol.toStringTag): "GeneratorFunction"}
    next:? next()
    return:? return()
    throw:? throw()
    Symbol(Symbol.toStringTag):"Generator"
    __proto__:Object
[[GeneratorStatus]]:"suspended"
[[GeneratorFunction]]:?* greneratorDome()
[[GeneratorReceiver]]:Window
[[GeneratorLocation]]:test.html:43
[[Scopes]]:Scopes[3]

通過上面的輸出結(jié)果可以看的出來,沿著原型鏈向上查找就存在一個next方法,這個方法與Iterator接口返回的結(jié)果是大同小異的。

繼續(xù)延續(xù)dome代碼,并使用next方法向下執(zhí)行。

function * greneratorDome(){
    yield "Hello";
    yield "World";
    return "Ending";
}
let grenDome = greneratorDome();
console.log(grenDome.next());
// {value: "Hello", done: false}
console.log(grenDome.next());
// {value: "World", done: false}
console.log(grenDome.next());
// {value: "Ending", done: true}
console.log(grenDome.next());
// {value: undefined, done: true}

在最開始的地方有提到過Generator函數(shù),最后返回的是一個Iterator對象,這也就不難理解了。

異步的Generator

dome

function a (){
    setTimeout(() => {
        alert("我是后彈出");
    },1000)
}
function b (){
    alsert("我是先彈出");
}
function * grenDome (){
    yield a();
    yield b();
}
let gren = grenDome();
gren.next();
gren.next();
// 輸出結(jié)果
// 我是先彈出
// 我是后彈出

結(jié)合Promise

function a (){
    return new Promise((resolve,reject) => {
        setTimeOut(() => {
            console.log(1)
            resolve("a");
        })
    })
}
function b (){
    return new Promise((resolve,reject) => {
         console.log(2)
        resolve("b");
    })
}
function * grenDome (){
    yield a();
    yield b();
    return new Promise((resolve,reject) => {
        resolve("grenDome內(nèi)部")
    })
}
let gren = grenDome();

// console.log(gren.next())
// {value: Promise, done: false}
// console.log(gren.next())
// {value: Promise, done: false}
// console.log(gren.next())
// {value: Promise, done: true}
// console.log(gren.next())
// {value: undefined, done: true}

gren.next().value.then((res) => {
    console.log(res);
    // a函數(shù)
})
gren.next().value.then((res) => {
    console.log(res);
    // b函數(shù)
})
gren.next().value.then((res) => {
    console.log(res);
    // grenDome內(nèi)部
})
// 輸出結(jié)果
// a
// b
// grenDome內(nèi)部

在上面的代碼中有一點(diǎn)是需要注意的,在grenDome函數(shù)里面最后return出去了一個Promise,但是在輸出的時候雖然done屬性已經(jīng)為true但是value里面仍然會存有一個promise對象,實(shí)際上done表示的是對應(yīng)yield關(guān)鍵字的函數(shù)已經(jīng)遍歷完成了。

Async/Await

Async/awaitJavascript編寫異步程序的新方法。以往的異步方法無外乎回調(diào)函數(shù)和Promise。但是Async/await建立于Promise之上,換句話來說使用了Generator函數(shù)做了語法糖。

async函數(shù)就是隧道盡頭的亮光,很多人認(rèn)為它是異步操作的終極解決方案。

什么是Async/Await

async顧名思義是“異步”的意思,async用于聲明一個函數(shù)是異步的。而await從字面意思上是“等待”的意思,就是用于等待異步完成。并且await只能在async函數(shù)中使用。

Async/Await語法
function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
};
asyncPrint("hello world",2000);
// 在2000ms之后輸出`hello world`
返回Promse對象

通常asyncawait都是跟隨Promise一起使用的。為什么這么說呢?因?yàn)?b>async返回的都是一個Promise對象同時async適用于任何類型的函數(shù)上。這樣await得到的就是一個Promise對象,如果不是Promise對象的話那async返回的是什么就是什么。

async function f() {
  return "hello world";
}
f().then(v => console.log(v));
// hello world

async函數(shù)返回一個Promise對象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時候,一旦遇到await就會先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。

function a(){
    return new Promise((resolve,reject) => {
        console.log("a函數(shù)")
        resolve("a函數(shù)")
    })
}
function b (){
    return new Promise((resolve,reject) => {
        console.log("b函數(shù)")
        resolve("b函數(shù)")
    })
}
async function dome (){
    let A = await a();
    let B = await b();
    return Promise.resolve([A,B]);
}
dome().then((res) => {
    console.log(res);
});
執(zhí)行機(jī)制

前面已經(jīng)說過await是等待的意思,之后等前面的代碼執(zhí)行完成之后才會繼續(xù)向下執(zhí)行。

function a(){
    return new Promise((resolve,reject) => {
        resolve("a");
        console.log("a:不行")
    })
}
function b (){
    return new Promise((resolve,reject) => {
        resolve("b");
        console.log("b:不行");
    })
}
async function dome (){
    await a();
    await b();
    console.log("雖然我在后面,但是我想要先執(zhí)行可以么?")
}
dome();
// 輸出結(jié)果
// a:不行
// b:不行
// 雖然我在后面,但是我想要先執(zhí)行可以么?

另外一個列子

function timeout1(ms) {
  return new Promise((resolve) => {
    setTimeout(() => {
        console.log("timeout1")
        resolve();
    },ms);
  });
};
function timeout2(ms) {
  return new Promise((resolve) => {
    setTimeout(() => {
        console.log("timeout2");
        resolve();
    },ms);
  });
};
async function asyncPrint() {
  await timeout1(1000);
  await timeout2(2000);
};
asyncPrint().then((res) => {
    console.log(res);
}).catch((err) => {
    console.log(err)
})
// 1s 后輸出timeout1
// 3s 后輸出timeout2
// undefined
async、await錯誤處理

JavaScript異步請求肯定會有請求失敗的情況,上面也說到了async返回的是一個Promise對象。既然是返回一個Promise對象的話那處理當(dāng)異步請求發(fā)生錯誤的時候我們就要處理reject的狀態(tài)了。

在Promise中當(dāng)請求reject的時候我們可以使用catch。為了保持代碼的健壯性使用async、await的時候我們使用try catch來處理錯誤。

async function f() {
  await Promise.reject("出錯了");
  await Promise.resolve("hello world");
}

async function b() {
    try {
      await f();
    } catch(err) {
     console.log(err);
    }
}
b();
//  出錯了
總結(jié)
Iterator接口

遍歷器對象除了具有next方法,還可以具有return方法和throw方法。如果你自己寫遍歷器對象生成函數(shù),那么next方法是必須部署的,return方法和throw方法是否部署是可選的。

Es6提供很多API都是基于Iterator接口,比如解構(gòu),for...of循環(huán),拓展運(yùn)算等。

Generator函數(shù)

調(diào)用Generator函數(shù),返回一個遍歷器對象,代表Generator函數(shù)的內(nèi)部指針。以后每次調(diào)用遍歷器對象的next方法,就會返回一個有著valuedone兩個屬性的對象。
value屬性表示當(dāng)前的內(nèi)部狀態(tài)的值,是yield語句后面那個表達(dá)式的值;done屬性是一個布爾值,表示是否遍歷結(jié)束

Async/Await

Async/await是近些年來JavaScript最具革命性的新特性之一。他讓讀者意識到使用Promise存在的一些問題,并提供了自身來代替Promise的方案。他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者then來處理異步。

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

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

相關(guān)文章

  • JavaScript異步編程:GeneratorAsync

    摘要:從開始,就在引入新功能,來幫助更簡單的方法來處理異步編程,幫助我們遠(yuǎn)離回調(diào)地獄。而則是為了更簡潔的使用而提出的語法,相比這種的實(shí)現(xiàn)方式,更為專注,生來就是為了處理異步編程。 從Promise開始,JavaScript就在引入新功能,來幫助更簡單的方法來處理異步編程,幫助我們遠(yuǎn)離回調(diào)地獄。 Promise是下邊要講的Generator/yield與async/await的基礎(chǔ),希望你已...

    leon 評論0 收藏0
  • 理解 async/await

    摘要:而函數(shù)的命令后面則可以是或者原始類型的值,,,但這時等同于同步操作返回值是。拋出的錯誤而會被方法回調(diào)函數(shù)接收到。 ES7 提出的async 函數(shù),終于讓 JavaScript 對于異步操作有了終極解決方案。No more callback hell。async 函數(shù)是 Generator 函數(shù)的語法糖。使用 關(guān)鍵字 async 來表示,在函數(shù)內(nèi)部使用 await 來表示異步。想較于 G...

    kid143 評論0 收藏0
  • JS中的async/await -- 異步隧道盡頭的亮光

    摘要:結(jié)果輸出可以看出函數(shù)返回的是一個對象,如果函數(shù)中一個直接量,函數(shù)會封裝成對象返回,而如果沒有返回值時,函數(shù)會返回在沒有結(jié)合時,函數(shù)會立即執(zhí)行,返回一個對象。 JS中的異步操作從最初的回調(diào)函數(shù)演進(jìn)到Promise,再到Generator,都是逐步的改進(jìn),而async函數(shù)的出現(xiàn)仿佛看到了異步方案的終點(diǎn),用同步的方式寫異步。showImg(https://segmentfault.com/i...

    jaysun 評論0 收藏0
  • ES6 系列之我們來聊聊 Async

    摘要:標(biāo)準(zhǔn)引入了函數(shù),使得異步操作變得更加方便。在異步處理上,函數(shù)就是函數(shù)的語法糖。在實(shí)際項(xiàng)目中,錯誤處理邏輯可能會很復(fù)雜,這會導(dǎo)致冗余的代碼。的出現(xiàn)使得就可以捕獲同步和異步的錯誤。如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑垊?wù)必給予指正,十分感謝。 async ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù),使得異步操作變得更加方便。 在異步處理上,async 函數(shù)就是 Generator 函數(shù)的語法糖。 ...

    Songlcy 評論0 收藏0
  • 簡單理解Generator自執(zhí)行及asyncawait語法原理

    摘要:為了更加方便的處理異步操作問題,現(xiàn)在最新的前端框架生態(tài)都開始用上了和,有的甚至已經(jīng)開始使用最新的語法了,這兩樣都是基于自動執(zhí)行的原理。這里就簡單理解下自執(zhí)行及語法原理一函數(shù)函數(shù)指的是能將執(zhí)行結(jié)果傳入回調(diào)函數(shù),并將該回調(diào)函數(shù)返回的函數(shù)。 為了更加方便的處理異步操作問題,現(xiàn)在最新的前端框架生態(tài)都開始用上了Generator和yield,有的甚至已經(jīng)開始使用最新的async、await語法了...

    stackfing 評論0 收藏0

發(fā)表評論

0條評論

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