日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

“约见”面试官系列之常见面试题第三十二篇之async和await(建议收藏)

發(fā)布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “约见”面试官系列之常见面试题第三十二篇之async和await(建议收藏) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、async和await

  • async和await的概念

  • 1)async 函數(shù)是 Generator 函數(shù)的語法糖,使用 關(guān)鍵字 async 來表示,在函數(shù)內(nèi)部使用 await 來表示異步
    2)ES7 提出的async 函數(shù),終于讓 JavaScript 對于異步操作有了終極解決方案
    3)async 作為一個關(guān)鍵字放到函數(shù)的前面,用于表示函數(shù)是一個異步函數(shù),該函數(shù)的執(zhí)行不會阻塞后面代碼的執(zhí)行
    4)await是等待,只能放到async函數(shù)里面,在后面放一個返回promise對象的表達式
    5)async和await是為了解決大量復(fù)雜不易讀的Promise異步的問題

  • async函數(shù)的改進

  • 1)內(nèi)置執(zhí)行器,Generator 函數(shù)的執(zhí)行必須依靠執(zhí)行器,而 Aysnc 函數(shù)自帶執(zhí)行器,調(diào)用方式跟普通函數(shù)的調(diào)用一樣
    2)更好的語義,async 和 await 相較于 * 和 yield 更加語義化
    3)更廣的適用性,co 模塊約定,yield 命令后面只能是 Thunk 函數(shù)或 Promise對象,而 async 函數(shù)的 await 命令后面則可以是 Promise 或者 原始類型的值(Number,string,boolean,但這時等同于同步操作)
    4)返回值是 Promise,async 函數(shù)返回值是 Promise 對象,比 Generator 函數(shù)返回的 Iterator 對象方便,可以直接使用 then() 方法進行調(diào)用
    5)async方式,流程清晰,直觀、語義明顯,操作異步流程就如同操作同步流程, async 函數(shù)自帶執(zhí)行器,執(zhí)行的時候無需手動加載。對于Promise的方式,如果處理流程復(fù)雜,整段代碼將會充滿then,不然很好的表示流程。對于Generator 方式,函數(shù)的執(zhí)行需要依靠執(zhí)行器,每次都需要通過 g.next() 的方式去執(zhí)行

  • async和await的實例

  • 1)async 作為一個關(guān)鍵字放到函數(shù)的前面,用于表示函數(shù)是一個異步函數(shù),該函數(shù)的執(zhí)行不會阻塞后面代碼的執(zhí)行
    實例代碼:

    async function timeout(){return "hello word";}timeout();// Promise __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: "hello word"//async返回的是 promise 對象console.log(timeout());// 我在后面,但是我是先執(zhí)行的console.log("我在后面,但是我是先執(zhí)行的");

    2)async聲明的函數(shù)的返回本質(zhì)上是一個Promise,async函數(shù)內(nèi)部會返回一個Promise對象,then方法回調(diào)函數(shù)的參數(shù)
    實例代碼:

    // hello world11async function f1(){return "hello world11";};f1().then((v)=>console.log(v));

    3)await的本質(zhì)是可以提供等同于”同步效果“的等待異步返回能力的語法糖,用await聲明的Promise異步返回,必須“等待”到有返回值的時候,代碼才繼續(xù)執(zhí)行下去
    實例代碼:

    /* hello1我是hello2輸出 hello1*/const test = async()=>{let message = "hello1";let result = await message;console.log(result);console.log("我是hello2");return result;};test().then(result =>{console.log("輸出",result);});

    4)async 函數(shù)內(nèi)部的實現(xiàn)原理是resolved,如果函數(shù)內(nèi)部拋出錯誤, 則會導(dǎo)致返回的 Promise 對象狀態(tài)變?yōu)?reject 狀態(tài),promise 對象有一個catch 方法進行捕獲,被 catch 方法回調(diào)函數(shù)接收到
    實例代碼:

    async function timeout2(flag){if(flag){return "hello world";}else{throw "failed";}}// 如果函數(shù)內(nèi)部拋出錯誤, promise 對象有一個catch 方法進行捕獲timeout2(false).catch(err => {console.log(err);});// hello word// 調(diào)用Promise.resolve() 返回promise 對象console.log(timeout2(true));// Uncaught (in promise) failed// 調(diào)用Promise.reject() 返回promise 對象console.log(timeout2(false));

    5)async必須聲明的是一個function,await就必須是在這個async聲明的函數(shù)內(nèi)部使用,必須是直系,作用域鏈不能隔代,在后面放一個返回promise對象的表達式
    實例代碼:

    // 需求:2s后讓數(shù)值乘以2function doubleAfter(num){return new Promise((resolve,reject)=>{setTimeout(()=>{resolve(2*num)},2000);});}// 60// 等待2s后,promis開始resolve,返回值async function test(){let result = await doubleAfter(30);console.log(result);}test();// 240//等待6s后,promis開始resolve,返回值async function test2(){let first = await doubleAfter(30);let second = await doubleAfter(40);let third = await doubleAfter(50);console.log(first+second+third);}test2();

    6)函數(shù)的錯誤處理,當 async 函數(shù)中只要一個 await 出現(xiàn) reject 狀態(tài),則后面的 await 都不會被執(zhí)行,可以添加 try/catch
    實例代碼:

    let a;async function f5(){await Promise.reject("error");a = await 1;}//f5().then(v=>console.log(a));// try/catch 解決// Uncaught (in promise) ReferenceError: error is not definedat f6 (test13.html:124)let a3;async function f6(){try{await Promise.reject("error");}catch{console.log(error);}a3 = await 123;return a3;}f6().then((v)=>console.log(a3));
  • async/await的實戰(zhàn)

  • 1)需求分析:有兩個延時函數(shù),先延時1秒,在延遲2秒,再延時1秒,最后輸出“完成”
    2)實例代碼:

    // 延時函數(shù) const setDelay = (millisecond) => {return new Promise((resolve, reject)=>{if (typeof millisecond != 'number') reject(new Error('參數(shù)必須是number類型'));setTimeout(()=> {resolve(`我延遲了${millisecond}毫秒后輸出的`)}, millisecond)}) } const setDelaySecond = (seconds) => {return new Promise((resolve, reject)=>{if (typeof seconds != 'number' || seconds > 10) reject(new Error('參數(shù)必須是number類型,并且小于等于10'));setTimeout(()=> {resolve(`我延遲了${seconds}秒后輸出的,注意單位是秒`)}, seconds * 1000)}) }/* 我延遲了${millisecond}毫秒后輸出的我延遲了${seconds}秒后輸出的,注意單位是秒我延遲了${millisecond}毫秒后輸出的完成*/ (async ()=>{const result = await setDelay(1000);console.log(result);console.log(await setDelaySecond(2));console.log(await setDelay(1000));console.log('完成了'); })()

    二、async和await的面試題總結(jié)

  • 談?wù)剬?async/await 的理解,async/await 的實現(xiàn)原理是什么?
    1)async/await 就是 Generator 的語法糖,使得異步操作變得更加方便
    2)async 函數(shù)就是將 Generator 函數(shù)的星號(*)替換成 async,將 yield 替換成await
    3)async 是 Generator 的語法糖,這個糖體現(xiàn)在這幾個方面:
    • async函數(shù)內(nèi)置執(zhí)行器,函數(shù)調(diào)用之后,會自動執(zhí)行,輸出最后結(jié)果,而Generator需要調(diào)用next或者配合co模塊使用
    • 更好的語義,async和await,比起星號和yield,語義更清楚了,async表示函數(shù)里有異步操作,await表示緊跟在后面的表達式需要等待結(jié)果
    • 更廣的適用性,co模塊約定,yield命令后面只能是 Thunk 函數(shù)或 Promise 對象,而async 函數(shù)的 await 命令后面,可以是 Promise 對象和原始類型的值
    • 返回值是Promise,async函數(shù)的返回值是 Promise 對象,Generator的返回值是 Iterator,Promise 對象使用起來更加方便
      4)async/await 函數(shù)的實現(xiàn)原理,就是將 Generator 函數(shù)和自動執(zhí)行器,包裝在一個函數(shù)里
      5)實例代碼分析:
    function my_co(it) {return new Promise((resolve, reject) => {function next(data) {try {var { value, done } = it.next(data);}catch(e){return reject(e);}if (!done) { //done為true,表示迭代完成//value 不一定是 Promise,可能是一個普通值。使用 Promise.resolve 進行包裝。Promise.resolve(value).then(val => {next(val);}, reject);} else {resolve(value);}}next(); //執(zhí)行一次next}); } function* test() {yield new Promise((resolve, reject) => {setTimeout(resolve, 100);});yield new Promise((resolve, reject) => {// throw Error(1);resolve(10)});yield 10;return 1000; }my_co(test()).then(data => {console.log(data); //輸出1000 }).catch((err) => {console.log('err: ', err); });
  • 使用 async/await 需要注意什么?
    1)await 命令后面的Promise對象,運行結(jié)果可能是 rejected,此時等同于 async 函數(shù)返回的 Promise 對象被reject。因此需要加上錯誤處理,可以給每個 await 后的 Promise 增加 catch 方法;也可以將 await 的代碼放在 try…catch 中
    2)多個await命令后面的異步操作,如果不存在繼發(fā)關(guān)系,最好讓它們同時觸發(fā)
    實例代碼:
  • //下面兩種寫法都可以同時觸發(fā) //法一 async function f1() {await Promise.all([new Promise((resolve) => {setTimeout(resolve, 600);}),new Promise((resolve) => {setTimeout(resolve, 600);})]) } //法二 async function f2() {let fn1 = new Promise((resolve) => {setTimeout(resolve, 800);});let fn2 = new Promise((resolve) => {setTimeout(resolve, 800);})await fn1;await fn2; }

    3)await命令只能用在async函數(shù)之中,如果用在普通函數(shù),會報錯
    4)async 函數(shù)可以保留運行堆棧
    實例代碼:

    / * 函數(shù)a內(nèi)部運行了一個異步任務(wù)b()。當b()運行的時候,函數(shù)a()不會中斷,而是繼續(xù)執(zhí)行。 * 等到b()運行結(jié)束,可能a()早就* 運行結(jié)束了,b()所在的上下文環(huán)境已經(jīng)消失了。 * 如果b()或c()報錯,錯誤堆棧將不包括a()。 */ function b() {return new Promise((resolve, reject) => {setTimeout(resolve, 200)}); } function c() {throw Error(10); } const a = () => {b().then(() => c()); }; a(); /** * 改成async函數(shù) */ const m = async () => {await b();c(); }; m();

    ?

    • 本面試題為前端常考面試題,后續(xù)有機會繼續(xù)完善。我是歌謠,一個沉迷于故事的講述者。

      歡迎一起私信交流。

      “睡服“面試官系列之各系列目錄匯總(建議學(xué)習(xí)收藏)?

    總結(jié)

    以上是生活随笔為你收集整理的“约见”面试官系列之常见面试题第三十二篇之async和await(建议收藏)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。