<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Async/await 有一種特殊的語法可用一種更舒適的方式使用 promise,稱為 "async/await"。 ## Async 函數 我們從`async`關鍵字開始。它可以放在函數前,就像這樣: ~~~js async function f() { return 1; } ~~~ > 函數前的 "async" 意味著一件簡單的事情:函數總是會返回 promise。如果代碼中有`return <non-promise>`,那么 JavaScript 就會自動將其封裝到一個帶有該值的 resolved promise 中。 例如,上述代碼中返回一個帶有結果`1`的 resolved promise,我們可以進行測試: ~~~js async function f() { return 1; } f().then(alert); // 1 ~~~ 我們可以顯式的返回一個 promise,結果相同: ~~~js async function f() { return Promise.resolve(1); } f().then(alert); // 1 ~~~ 因此,`async`確保函數返回一個 promise,并在其中封裝非 promise。很簡單對吧?但不僅僅如此。因為還有`await`關鍵字,它只在`async`函數中工作,而且非常酷。 ## Await 語法: ~~~js // 只在 async 函數中工作 let value = await promise; ~~~ `await`關鍵字使 JavaScript 等待,直到 promise 得到解決并返回其結果。 下面是一個 promise 在 1s 之后 resolve 的例子: ~~~js async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve("done!"), 1000) }); let result = await promise; // 等待,直到 promise 執行 resolves (*) alert(result); // “done!” } f(); ~~~ 函數在`(*)`行執行“暫停”,并在 promise 被處理時繼續執行,`result`變成其結果。上述代碼在一秒內顯示了 "done!" > `await`字面上是讓 JavaScript 等待 promise 完成,然后繼續處理結果。這并不會消耗 CPU 資源,因為引擎可以同時處理其他任務:執行其他腳本,處理事件等。 這是一種比`promise.then`更優雅地獲取 promise 結果的語法,它更容易閱讀和編寫。 > 不能在常規函數中使用`await`" 如果我們嘗試在非 async 函數中使用 `await`,就會產生語法錯誤: ~~~js function f() { let promise = Promise.resolve(1); let result = await promise; // 語法錯誤 } ~~~ 如果我們忘記將`async`放在函數前,我們就會得到這樣的錯誤。如前面所說的,`await`只在`async 函數`中工作。 ```js async function showAvatar() { // 讀取我們的 JSON let response = await fetch('/article/promise-chaining/user.json'); let user = await response.json(); // 讀取 GitHub 用戶信息 let githubResponse = await fetch(`https://api.github.com/users/${user.name}`); let githubUser = await githubResponse.json(); // 顯示化身 let img = document.createElement('img'); img.src = githubUser.avatar_url; img.className = "promise-avatar-example"; document.body.append(img); // 等待 3 秒 await new Promise((resolve, reject) => setTimeout(resolve, 3000)); img.remove(); return githubUser; } showAvatar(); ``` 非常整潔,而且易于閱讀,對吧?比之前好多了。 ## `await` 在頂層代碼中無效 剛開始使用 `await` 的新手往往會忘記這一點,但我們不能在最頂層的代碼中編寫 `await`,因為它會無效: ```js run // 在頂層代碼中導致語法錯誤 let response = await fetch('/article/promise-chaining/user.json'); let user = await response.json(); ``` 所以我們需要將 await 代碼封裝在一個async 函數中。就像上述例子一樣。 `await`接受 thenables" 像 `promise.then`、`await` 允許使用 thenable 對象(那些具有可調用的 `then` 方法)。同樣,我們的想法是,第三方對象可能不是 promise,而是與 promise 兼容:如果它支持 `.then`,那么就可以和 `await` 一起使用。 例如,這里的`await`接受`new Thenable(1)`: ~~~js class Thenable { constructor(num) { this.num = num; } then(resolve, reject) { alert(resolve); // function() { native code } // 在 1000 ms 后將 this.num*2 作為 resolve 值返回 setTimeout(() => resolve(this.num * 2), 1000); // (*) } }; async function f() { // 等待 1 秒后,結果變成 2 let result = await new Thenable(1); alert(result); } f(); ~~~ 如果`await`獲取了帶有`.then`的非 promise 對象,它就會調用提供`resolve`、`reject`作為參數的原生函數。`await`等待,直到其中一個被調用(在上述示例中,發生在`(*)`行),然后繼續處理結果。 ## Async 方法 類方法也可以 async,只要把 `async` 放在類方法前即可。 就像這樣: ```js class Waiter { *!* async wait() { */!* return await Promise.resolve(1); } } new Waiter() .wait() .then(alert); // 1 ``` 意義相同:它確保返回值是 promise,并使 `await` 可用。 ## Error 處理 如果一個 promise 正常 reslove,那么`await promise`就會返回結果。但在 reject 情況下,它會拋出 error,就像該行上有`throw`語句一樣。 代碼: ~~~js async function f() { await Promise.reject(new Error("Whoops!")); } ~~~ 與此相同: ~~~js async function f() { throw new Error("Whoops!"); } ~~~ 在實際情況中,promise 可能需要一段時間才會變成 reject。因此`await`會等待,然后拋出 error。 我們可以使用`try..catch`來捕獲這個 error,就像常規`throw`方法一樣: ~~~js async function f() { try { let response = await fetch('http://no-such-url'); } catch(err) { *!* alert(err); // 類型錯誤:獲取失敗 */!* } } f(); ~~~ 出錯時,控制權會進入`catch`塊。我們也可以封裝多行: ~~~js async function f() { try { let response = await fetch('/no-user-here'); let user = await response.json(); } catch(err) { // catches errors both in fetch and response.json alert(err); } } f(); ~~~ 如果我們沒有`try..catch`,那么 async 函數`f()`調用所產生的 promise 就會變為 reject 狀態。我們可以通過追加`.catch`來處理它: ~~~js async function f() { let response = await fetch('http://no-such-url'); } // f() 變成一個 rejected 狀態的 promise *!* f().catch(alert); // 類型錯誤:未能獲取 // (*) */!* ~~~ 如果忘記在那里添加`.catch`,那么我們就會得到一個未處理的 promise 錯誤(可以在控制臺中看到)。我們可以像 info:promise-chaining 章節所描述的那樣,使用一個全局事件處理器來捕獲這樣的 error。 ```smart header="`async/await`和 `promise.then/catch`" 我們使用 `async/await` 時,幾乎不需要 `.then`,因為 `await` 為我們處理等待。我們也可以使用 `try..catch` 替代 `.catch`。但這通常(并不總是)更方便。 但是在代碼的頂層,當我們在`async`函數的外部時,我們在語法上是不能使用`await`的,所以通常添加`.then/catch`去處理最終結果或者 error。 與上述示例的`(*)`行一樣。 ~~~ ````smart header="`async/await` 可以很好的與 `Promise.all` 協同工作" 當我們需要等待多個 promise 時,我們可以將它們封裝進 `Promise.all` 然后 `await`: ```js // wait for the array of results let results = await Promise.all([ fetch(url1), fetch(url2), ... ]); ~~~ 產生 error 的情況下,它會像往常一樣傳輸:從失敗的 promise 到`Promise.all`,然后變成一個我們可以使用`try..catch`捕獲的異常。 ## 總結 函數前的 `async` 關鍵字有兩個作用: 1. 總是返回 promise。 2. 允許在其中使用 `await`。 在 promise 之前的 `await` 關鍵字,使 JavaScript 等待 promise 被處理,然后: 1. 如果有 error,就會產生異常,就像在那個地方調用了 `throw error` 一樣。 2. 否則,就會返回值,我們可以給它分配一個值。 它們一起為編寫易于讀寫的異步代碼提供了一個很好的框架。 對于 `async/await`,我們很少需要編寫 `promise.then/catch`,但我們不應該忘記它們是基于 promise 的。因為有時(例如,在最外面的范圍)
                  <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>

                              哎呀哎呀视频在线观看