<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                async/await 是一種特殊的語法,能夠更好的處理promise,可以讓你編寫基于Promise的代碼像同步一樣。 ### async async 關鍵字放在函數之前,使得該函數總是返回一個promise對象。如果代碼中顯式 return 了一個值,那么函數的返回值將會被自動包裝成resolved狀態下的promise對象。 例如: ~~~js async function fn() { return 1; } fn().then(res => { console.log(res) // 1 }) ~~~ ##### async函數的使用方式 ~~~js // 函數聲明式 async function fn() { } // 函數表達式 const fn = async function () { } // ArrowFunc const fn = async () => {} // 對象中定義 let obj = { async fn() {} } ~~~ 當async函數被調用執行的時候,會返回一個Promise的實例。當函數返回值時,promise會執行。如果函數在執行中拋出錯誤,那么會進入promise的rejected流程。 比如: ~~~js const foo = async () => { throw new Error('err'); } foo() .then(res => { console.log(res); }) .catch(err=> { console.log(err) // Error: err }) ~~~ ### await await關鍵字只能在async函數中使用。可以用來等待Promise狀態變成resolved并有返回值。await后面通常跟的是一個promise對象,如果不是,會立即被包裝成resoled狀態的promise。 ~~~js async function foo() { let result = await 'ok' console.log(result); // ok } foo(); ~~~ 1. 當用變量接收await的返回值時,值為promise為resolved狀態下的值。 ~~~js const foo = async () => { let result = await Promise.resolve('ok'); console.log(result); // ok } foo(); ~~~ 2. 函數執行中,遇到await,會首先返回promise,狀態為pending,并且下面的代碼會停止執行,待awiat后面的Promise執行完畢后才繼續執行下面的代碼,直到函數體中的代碼全部執行完畢后,函數返回的promise狀態才變成resolved。 ~~~js function bar() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('ok'); }, 1000); }) } async function foo() { let result = await bar(); console.log(result); // ok console.log('last'); } console.log(foo()); ~~~ 輸出順序: ![](//upload-images.jianshu.io/upload_images/5256541-6b676362c10c14a3.png?imageMogr2/auto-orient/strip|imageView2/2/w/389/format/webp) Markdown 首先打印出pending狀態的promise對象。 等到await后面的異步函數執行完后,才依次打印出ok、last,同時Promise的狀態成為resolved。 ![](//upload-images.jianshu.io/upload_images/5256541-8cb6f6e09093d7c8.png?imageMogr2/auto-orient/strip|imageView2/2/w/462/format/webp) Markdown 由此可以看出,當在async函數中運行,當遇到await關鍵字時,會等待關鍵字后面的函數執行完畢才運行后面的代碼。當所有的執行完后函數返回的Promise對象的狀態才變成resolved。 ### 異常處理 我們知道在promise中是通過catch來捕獲異常的。但是在async中則使用try/catch來捕獲異常。 1. 如果await后面的 promise 正常resolve,await promise便會返回結果。但是在reject的情況下,便會拋出異常,并且這種異常需要用try/catch來捕獲,否則會導致進程崩潰。 ~~~js const baz = () => { return Promise.reject('Oops'); } const foo = async () => { try { await baz(); } catch(e) { // e 為 baz()返回的promise對象中 reject出來的值 console.log(e); // Oops } } foo(); ~~~ 2. 如果try中有多個await,其中一個await后面的promise為reject,那么在catch中會拋出第一個異常。 如下: ~~~js // 異步操作,返回promise對象 const bar = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject('Oops bar error'); }, 1000) }) } const baz = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject('Oops baz error'); }, 1000) }) } const foo = async () => { try { await bar(); await baz(); } catch(e) { // e 為 bar()返回的promise對象中 reject出來的值 console.log(e); // Oops bar error } } foo(); ~~~ 由此可以如果有多個 await 后面的promise都為reject狀態時,只能捕獲第一個異常。 3. 以下這種方式都會捕獲到。由于是同步的效果,所以第二次捕獲的異常是第一次捕獲1s后。 ~~~js const fn = async () => { try { await bar(); } catch (e) { console.log(e) // Oops bar error } try { await baz(); } catch (e) { console.log(e) // Oops baz error } } fn(); // 第二次和第一次的順序相隔1s ~~~ 4. 如果await后面的promise中拋出異常,那么等同于async函數返回的 Promise 對象被reject。如下: ~~~js async function foo() { await new Promise((resolve, reject) => { throw new Error('Oops'); }); } foo() .then(res => console.log('ok', res)) .catch(err => console.log('faile', err)) // faile Error: Oops ~~~ 5. try里邊的promise中的異常不會在catch中捕獲,因為異常發生在promise中,只能通過promise的catch()捕獲。 ~~~js const foo = () => { return new Promise((resolve, reject) => { resolve('ok'); }) } const bar = () => { try { foo() .then(res => { let data = JSON.parse(res); }).catch(err => { console.log(err); // SyntaxError: Unexpected token o in JSON at position 0 }) } catch(e) { // 這里不會捕獲到promise中的異常 console.log(e); } } bar(); ~~~ #### 并行和串行 1. 串行 如果有多個await,那么會按照順序一個個的執行。 ~~~js const p1 = async () => { return new Promise(resolve => { setTimeout(() => { resolve({ name: 'Rose' }) }, 1000); }) } const p2 = async () => { return new Promise(resolve => { setTimeout(() => { resolve({ name: 'Rose' }) }, 1000); }) } const getInfo = async () => { console.time('total time'); let p1Info = await p1(); let p2Info = await p2(); console.timeEnd('total time'); // total time: 2006.705810546875ms } getInfo() ~~~ 因為每個await后面的異步函數都會延時1s,所以總耗時大于2s。 2. 并行 如果有多個await,那么先將await后面的異步函數的返回值保存變量中。 ~~~js const getInfo = async() => { console.time('total time'); const [p1Info, p2Info] = await Promise.all([ p1(), p2() ]) console.timeEnd('total time'); // total time: 1003.5810546875ms } getInfo() ~~~ Promise.all()返回值是一個新的promise對象,值為數組。 3. 循環中的串行 ~~~js const p = async (name) => { return new Promise(resolve => { let user = {name}; setTimeout(() => { resolve(user) }, 1000) }) } let arr = ['bob', 'mike']; const getInfo = async() => { console.time('total time'); for (let name of arr) { const p3Info = await p(name); // 每隔1s輸出一次 console.log(p3Info.name); } console.timeEnd('total time'); // total time: 2007.77783203125ms } ~~~ 輸出順序: bob mike total time: 2007.77783203125ms 4. 循環中串行改并行 ~~~js const getInfo = async() => { console.time('total time'); // 將所有的promise對象保存在數組中 let promises = arr.map(name => { return p3(name); }) for(let promise of promises) { const Info = await promise; console.log(Info.name); } console.timeEnd('total time'); // total time: 1006.291015625ms } ~~~ ### 總結: #### async函數之前的關鍵字有兩個作用: 1. 使它總是返回一個promise。 2. 允許在其中使用await。 #### await promise之前的關鍵字使得JavaScript等待,直到這個promise的狀態為resolved 1. 如果是reject,則產生異常,需通過try/catch捕獲。 2. 否則,它返回結果,所以我們可以將它的值賦值給一個變量。 async/await使我們少寫promise.then/catch,但是不要忘記它們是基于promise的。 此外,網上很多關于promise的文章都會提到ajax的回調地獄,以此來說明promise的誕生只是用來解決異步的,其實不然。promise 只是解決異步的一種方式。 如果使用async/await,不僅代碼簡介,甚至有同步的feel。 promise是一種語法、一種形式,目前很多東西都是基于promise實現的,比如:jquery中的ajax,fetch,以及vue react中的很多功能也都使用了promise。所以promise是最最基本的。 0人點贊 [ECMAScript Next](/nb/16084136) 作者:一蕭煙雨任平生 鏈接:https://www.jianshu.com/p/fd3d571e38db 來源:簡書 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看