aboutsummaryrefslogtreecommitdiff
path: root/files/zh-tw/web/javascript/reference/statements/async_function/index.html
blob: ced67f4a09ebb5965f7bdaf989dd93055f51b30f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
---
title: async function
slug: Web/JavaScript/Reference/Statements/async_function
tags:
  - JavaScript
  - 函式
  - 實驗
  - 範例
  - 陳述
translation_of: Web/JavaScript/Reference/Statements/async_function
---
<div>{{jsSidebar("Statements")}}</div>

<p><code><strong>async function</strong></code> 宣告被定義為一個回傳 {{jsxref("Global_Objects/AsyncFunction","AsyncFunction")}} 物件的<em>非同步函式</em></p>

<div class="noinclude">
<p>你也可以使用 {{jsxref("Operators/async_function", "async function expression", "", 1)}} 來定義一個<em>非同步函式</em></p>
</div>

<h2 id="語法">語法</h2>

<pre class="syntaxbox">async function <em>name</em>([<em>param</em>[, <em>param</em>[, ... <em>param</em>]]]) {
   <em>statements</em>
}
</pre>

<h3 id="參數">參數</h3>

<dl>
 <dt><code>name</code></dt>
 <dd>函式名稱。</dd>
</dl>

<dl>
 <dt><code>param</code></dt>
 <dd>傳遞至函式的參數名稱。</dd>
</dl>

<dl>
 <dt><code>statements</code></dt>
 <dd>組成該函式主體的陳述。</dd>
</dl>

<h3 id="回傳值">回傳值</h3>

<p>{{jsxref("Global_Objects/AsyncFunction","AsyncFunction")}} 物件,代表著一個非同步函式,該函式會執行該函式內的程式碼。</p>

<h2 id="描述">描述</h2>

<p><code>async</code> 函式被呼叫時,它會回傳一個 {{jsxref("Promise")}}。如果該 <code>async</code> 函式回傳了一個值,<code>Promise</code> 的狀態將為一個帶有該回傳值的 resolved。如果 <code>async</code> 函式拋出例外或某個值,<code>Promise</code> 的狀態將為一個帶有被拋出值的 rejected。</p>

<p>async 函式內部可以使用 {{jsxref("Operators/await", "await")}} 表達式,它會暫停此 async 函式的執行,並且等待傳遞至表達式的 Promise 的解析,解析完之後會回傳解析值,並繼續此 async 函式的執行。</p>

<div class="note">
<p><code>async/await</code> 函式的目的在於簡化同步操作 promise 的表現,以及對多個 <code>Promise</code> 物件執行某些操作。就像 <code>Promise 類似於具結構性的回呼函式,同樣地,async/await 好比將 generator 與 promise 組合起來。</code></p>
</div>

<h2 id="範例">範例</h2>

<h3 id="簡單範例">簡單範例</h3>

<pre class="brush: js">function resolveAfter2Seconds(x) {
  return new Promise(resolve =&gt; {
    setTimeout(() =&gt; {
      resolve(x);
    }, 2000);
  });
}


async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}

add1(10).then(v =&gt; {
  console.log(v);  // prints 60 after 4 seconds.
});


async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + await p_a + await p_b;
}

add2(10).then(v =&gt; {
  console.log(v);  // prints 60 after 2 seconds.
});
</pre>

<div class="warning">
<h4 id="不要誤解_Promise.all_的_await">不要誤解 <code>Promise.all</code><code>await</code></h4>

<p><code>add1</code> 裡,該執行為了第一個 <code>await</code> 而暫停了兩秒,接著為了第二個 <code>await</code> 又暫停了兩秒。在第一個計時器(timer)被觸發前,第二個計時器並不會被建立。而在 <code>add2</code> 裡,兩個計時器都被建立起來、也都執行 <code>await</code> 過了。這把它帶往了 resolve 所的 2 秒暫停、而不是 4 秒暫停。然而這兩個 <code>await</code> 呼叫都在連續運行,而非平行運行。<code>await</code> <strong>並不是</strong> <code>Promise.all</code> 的自動程式。如果你想讓兩個、甚至兩個以上的 <code>await</code> promises 同時執行(in parallel),你必須使用 <code>Promise.all</code>.</p>
</div>

<h3 id="使用_async_function_改寫_promise_鏈">使用 async function 改寫 promise 鏈</h3>

<p>一個 API 呼叫所回傳的 {{jsxref("Promise")}} 會導致一個 promise 鏈,將函式分隔成多個部份。考慮下列的程式碼:</p>

<pre class="brush: js">function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e =&gt; {
      return downloadFallbackData(url); // returns a promise
    })
    .then(v =&gt; {
      return processDataInWorker(v); // returns a promise
    });
}
</pre>

<p>它可以用一個簡單的 <code>async function</code> 來改寫成這樣:</p>

<pre class="brush: js">async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch(e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
</pre>

<p>注意上方的範例,在 return 陳述中沒有使用 await 陳述,這是因為 async function 的回傳值隱含地被包裝於 {{jsxref("Promise.resolve")}} 之中。</p>

<h2 id="規範">規範</h2>

<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">規範</th>
   <th scope="col">狀態</th>
   <th scope="col">註解</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-async-function-definitions', 'async function')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>Initial definition in ES2017.</td>
  </tr>
 </tbody>
</table>

<h2 id="瀏覽器相容性">瀏覽器相容性</h2>

<div>


<p>{{Compat("javascript.statements.async_function")}}</p>
</div>

<h2 id="參見">參見</h2>

<ul>
 <li>{{jsxref("Operators/async_function", "async function expression")}}</li>
 <li>{{jsxref("AsyncFunction")}} 物件</li>
 <li>{{jsxref("Operators/await", "await")}}</li>
 <li><a href="http://innolitics.com/10x/javascript-decorators-for-promise-returning-functions/">"Decorating Async Javascript Functions" on "innolitics.com"</a></li>
</ul>