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
|
---
title: for await...of
slug: Web/JavaScript/Reference/Statements/for-await...of
tags:
- JavaScript
- Reference
- Statement
- await
- for
- for await...of
- for...in
- for...of
- 异步
- 迭代
translation_of: Web/JavaScript/Reference/Statements/for-await...of
---
<p>{{jsSidebar("Statements")}}</p>
<p><strong><code>for await...of</code> 语句</strong>创建一个循环,该循环遍历异步可迭代对象以及同步可迭代对象,包括: <span style="">内置的 </span>{{jsxref("String")}}, {{jsxref("Array")}},<span style="">类似数组对象 (例如 </span>{{jsxref("Functions/arguments", "arguments")}} <span style="">或</span> {{DOMxRef("NodeList")}})<span style="">,</span>{{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}} <span style="">和用户定义的异步/同步迭代器。</span>它使用对象的每个不同属性的值调用要执行的语句来调用自定义迭代钩子。</p>
<p>类似于 {{jsxref("Operators/await", "await")}} 运算符一样,该语句只能在一个{{jsxref("Statements/async_function", "async function", "异步函数", 1)}} 内部使用。</p>
<div class="blockIndicator note">
<p><code>for await...of</code> 不适用于不是异步可迭代的异步迭代器。</p>
</div>
<h2 id="语法">语法</h2>
<pre class="syntaxbox notranslate">for await (<em>variable</em> of <em>iterable</em>) {
<em>statement
</em>}
</pre>
<dl>
<dt><code>variable</code></dt>
<dd>在每次迭代中,将不同属性的值分配给变量。变量有可能以<code>const</code>, <code>let</code>, 或者 <code>var</code>来声明。</dd>
<dt><code>iterable</code></dt>
<dd>被迭代枚举其属性的对象。与 for...of 相比,这里的对象可以返回 <code>Promise</code>,如果是这样,那么 <code>variable</code> 将是 <code>Promise</code> 所包含的值,否则是值本身。</dd>
</dl>
<h2 id="例子">例子</h2>
<h3 id="迭代异步可迭代对象">迭代异步可迭代对象</h3>
<p>你还可以迭代一个明确实现异步迭代协议的对象:</p>
<pre class="brush:js notranslate">var asyncIterable = {
[Symbol.asyncIterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return Promise.resolve({ value: this.i++, done: false });
}
return Promise.resolve({ done: true });
}
};
}
};
(async function() {
for await (num of asyncIterable) {
console.log(num);
}
})();
// 0
// 1
// 2
</pre>
<h3 id="迭代异步生成器">迭代异步生成器 </h3>
<p>异步生成器已经实现了异步迭代器协议, 所以可以用 <code>for await...of</code>循环。</p>
<pre class="brush: js notranslate">async function* asyncGenerator() {
var i = 0;
while (i < 3) {
yield i++;
}
}
(async function() {
for await (num of asyncGenerator()) {
console.log(num);
}
})();
// 0
// 1
// 2</pre>
<p>有关使用<code>for await... of</code>考虑迭代API中获取数据的异步 generator 更具体的例子。这个例子首先为一个数据流创建了一个异步 generator,然后使用它来获得这个API的响应值的大小。</p>
<pre class="brush: js notranslate">async function* streamAsyncIterator(stream) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
return;
}
yield value;
}
} finally {
reader.releaseLock();
}
}
// 从url获取数据并使用异步 generator 来计算响应值的大小
async function getResponseSize(url) {
const response = await fetch(url);
// Will hold the size of the response, in bytes.
let responseSize = 0;
// 使用for-await-of循环. 异步 generator 会遍历响应值的每一部分
for await (const chunk of streamAsyncIterator(response.body)) {
// Incrementing the total response length.
responseSize += chunk.length;
}
console.log(`Response Size: ${responseSize} bytes`);
// expected output: "Response Size: 1071472"
return responseSize;
}
getResponseSize('https://jsonplaceholder.typicode.com/photos');</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-for-in-and-for-of-statements', 'ECMAScript Language: The for-in, for-of, and for-await-of Statements')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ES2018', '#sec-for-in-and-for-of-statements', 'ECMAScript Language: The for-in, for-of, and for-await-of Statements')}}</td>
<td>{{Spec2('ES2018')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容">浏览器兼容</h2>
<div class="hidden">此页面上的兼容性表是根据结构化数据生成的。如果您想为数据做出贡献,请查看https://github.com/mdn/browser-compat-data并向我们发送拉取请求。</div>
<p>{{Compat("javascript.statements.for_await_of")}}</p>
<h2 id="相关链接">相关链接</h2>
<ul>
<li>{{jsxref("Global_Objects/Symbol/asyncIterator", "Symbol.asyncIterator")}}</li>
<li>{{jsxref("Statements/for...of")}}</li>
</ul>
|