回答編集履歴
9
テキスト修正
test
CHANGED
@@ -160,7 +160,7 @@
|
|
160
160
|
|
161
161
|
|
162
162
|
|
163
|
-
上記の 1. と 2. とは異なり、「200ミリ秒間隔でひと文字ずつ、最後の文字まで表示する」という処理をひとつの Promise にすることもできます。
|
163
|
+
上記の 1. と 2. とは異なり、「200ミリ秒間隔でひと文字ずつ、最後の文字まで表示する」という処理をひとつの Promise にすることもできます。以下のそのコード例です。
|
164
164
|
|
165
165
|
```javascript
|
166
166
|
|
@@ -214,14 +214,20 @@
|
|
214
214
|
|
215
215
|
```
|
216
216
|
|
217
|
-
|
217
|
+
|
218
|
-
|
219
|
-
|
220
218
|
|
221
219
|
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/14/](https://jsfiddle.net/jun68ykt/bcm7jgzw/14/)
|
222
220
|
|
223
221
|
|
224
222
|
|
223
|
+
上記では、
|
224
|
+
|
225
|
+
- `setTimeout`の替わりに`setInterval`を使っています。
|
226
|
+
|
227
|
+
- 文字列全体が表示されるまでをひとつの Promise にするので、 `Promise.all` は使わなくなっています。
|
228
|
+
|
229
|
+
- `Done.`という文字列を `resolve`の引数で返させるようにしました。
|
230
|
+
|
225
231
|
|
226
232
|
|
227
233
|
以上、参考になれば幸いです。
|
8
テキスト修正
test
CHANGED
@@ -160,27 +160,25 @@
|
|
160
160
|
|
161
161
|
|
162
162
|
|
163
|
-
上記の 1. と 2. とは異なり、「200ミリ秒間隔で
|
163
|
+
上記の 1. と 2. とは異なり、「200ミリ秒間隔でひと文字ずつ、最後の文字まで表示する」という処理をひとつの Promise にすることもできます。この場合は Promise.all は使わず、以下のようになります。
|
164
164
|
|
165
165
|
```javascript
|
166
166
|
|
167
|
-
const addTypingMovement = (word, target) =>
|
167
|
+
const addTypingMovement = (word, target) => new Promise(
|
168
|
-
|
168
|
+
|
169
|
-
|
169
|
+
resolve => {
|
170
|
-
|
170
|
+
|
171
|
-
const printTarget = document.querySelector(target);
|
171
|
+
const printTarget = document.querySelector(target);
|
172
|
-
|
173
|
-
|
174
|
-
|
172
|
+
|
175
|
-
|
173
|
+
let i = 0;
|
176
174
|
|
177
175
|
const intervalId = setInterval(
|
178
176
|
|
179
177
|
() => {
|
180
178
|
|
181
|
-
if (word
|
179
|
+
if (i < word.length) {
|
182
|
-
|
180
|
+
|
183
|
-
printTarget.textContent
|
181
|
+
printTarget.textContent = word.substring(0, ++ i);
|
184
182
|
|
185
183
|
} else {
|
186
184
|
|
@@ -192,9 +190,9 @@
|
|
192
190
|
|
193
191
|
}, 200);
|
194
192
|
|
195
|
-
});
|
196
|
-
|
197
|
-
}
|
193
|
+
}
|
194
|
+
|
195
|
+
);
|
198
196
|
|
199
197
|
|
200
198
|
|
@@ -220,7 +218,7 @@
|
|
220
218
|
|
221
219
|
|
222
220
|
|
223
|
-
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/
|
221
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/14/](https://jsfiddle.net/jun68ykt/bcm7jgzw/14/)
|
224
222
|
|
225
223
|
|
226
224
|
|
7
テキスト修正
test
CHANGED
@@ -174,8 +174,6 @@
|
|
174
174
|
|
175
175
|
return new Promise(resolve => {
|
176
176
|
|
177
|
-
let i = 0;
|
178
|
-
|
179
177
|
const intervalId = setInterval(
|
180
178
|
|
181
179
|
() => {
|
@@ -222,7 +220,7 @@
|
|
222
220
|
|
223
221
|
|
224
222
|
|
225
|
-
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/
|
223
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/5/](https://jsfiddle.net/jun68ykt/bcm7jgzw/5/)
|
226
224
|
|
227
225
|
|
228
226
|
|
6
テキスト修正
test
CHANGED
@@ -2,6 +2,24 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
この回答では3つのコードを挙げます。ご質問のタイトルに、
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
> for文内にsetTimeoutがある関数に対して、・・・
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
とあったので、 まずご質問のコードにある forループを生かしたコードを回答します。その後、for文を使わないコードを2つ挙げます。
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
### 1. forループで、各文字を追加するPromiseの配列を作る。
|
20
|
+
|
21
|
+
|
22
|
+
|
5
23
|
各文字を追加していく処理をひとつのPromiseにして、それらがすべてresolve されたら、Doneを表示するという前後関係を担保するために、 [Promise.all](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) を使えばよいかと思います。
|
6
24
|
|
7
25
|
|
@@ -70,7 +88,13 @@
|
|
70
88
|
|
71
89
|
|
72
90
|
|
73
|
-
|
91
|
+
|
92
|
+
|
93
|
+
### 2. forの替わりにmapを、前後関係の制御にasync/awaitを使用
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
上記 1. のコードで、Promiseの配列を作るところの for文を [map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) を使って書き換え、 すべての文字が `target` に追加されたら、Done を表示するために `async`, `await` を使った例が以下です。
|
74
98
|
|
75
99
|
|
76
100
|
|
@@ -130,74 +154,78 @@
|
|
130
154
|
|
131
155
|
|
132
156
|
|
157
|
+
### 3. 最後の文字まで表示するのを一つのPromiseにする。
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
上記の 1. と 2. とは異なり、「200ミリ秒間隔で各文字を追加するのを、最後の文字まで行う」という処理をひとつの Promise にすることもできます。この場合は Promise.all は使わず、以下のようになります。
|
164
|
+
|
165
|
+
```javascript
|
166
|
+
|
167
|
+
const addTypingMovement = (word, target) => {
|
168
|
+
|
169
|
+
const wordArray = [...word];
|
170
|
+
|
171
|
+
const printTarget = document.querySelector(target);
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
return new Promise(resolve => {
|
176
|
+
|
177
|
+
let i = 0;
|
178
|
+
|
179
|
+
const intervalId = setInterval(
|
180
|
+
|
181
|
+
() => {
|
182
|
+
|
183
|
+
if (wordArray.length > 0) {
|
184
|
+
|
185
|
+
printTarget.textContent += wordArray.shift();
|
186
|
+
|
187
|
+
} else {
|
188
|
+
|
189
|
+
clearInterval(intervalId);
|
190
|
+
|
191
|
+
resolve('Done.');
|
192
|
+
|
193
|
+
}
|
194
|
+
|
195
|
+
}, 200);
|
196
|
+
|
197
|
+
});
|
198
|
+
|
199
|
+
}
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
const finishTitleCall = (message) => {
|
204
|
+
|
205
|
+
document.querySelector('#result').textContent = message;
|
206
|
+
|
207
|
+
}
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
(async () => {
|
212
|
+
|
213
|
+
const message = await addTypingMovement('Hello World.', '#typing');
|
214
|
+
|
215
|
+
finishTitleCall(message);
|
216
|
+
|
217
|
+
})();
|
218
|
+
|
219
|
+
```
|
220
|
+
|
221
|
+
また上記では `Done.`という文字列を `resolve`の引数で返させました。
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/4/](https://jsfiddle.net/jun68ykt/bcm7jgzw/4/)
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
|
133
231
|
以上、参考になれば幸いです。
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
### 追記
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
別のやり方として、「200ミリ秒間隔で各文字を追加するのを、最後の文字まで行う」という処理をひとつの Promise にする方法もあります。この場合は Promise.all は使わず、以下のようになります。
|
142
|
-
|
143
|
-
```javascript
|
144
|
-
|
145
|
-
const addTypingMovement = (word, target) => {
|
146
|
-
|
147
|
-
const wordArray = [...word];
|
148
|
-
|
149
|
-
const printTarget = document.querySelector(target);
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
return new Promise(resolve => {
|
154
|
-
|
155
|
-
let i = 0;
|
156
|
-
|
157
|
-
const intervalId = setInterval(
|
158
|
-
|
159
|
-
() => {
|
160
|
-
|
161
|
-
if (wordArray.length > 0) {
|
162
|
-
|
163
|
-
printTarget.textContent += wordArray.shift();
|
164
|
-
|
165
|
-
} else {
|
166
|
-
|
167
|
-
clearInterval(intervalId);
|
168
|
-
|
169
|
-
resolve('Done.');
|
170
|
-
|
171
|
-
}
|
172
|
-
|
173
|
-
}, 200);
|
174
|
-
|
175
|
-
});
|
176
|
-
|
177
|
-
}
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
const finishTitleCall = (message) => {
|
182
|
-
|
183
|
-
document.querySelector('#result').textContent = message;
|
184
|
-
|
185
|
-
}
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
(async () => {
|
190
|
-
|
191
|
-
const message = await addTypingMovement('Hello World.', '#typing');
|
192
|
-
|
193
|
-
finishTitleCall(message);
|
194
|
-
|
195
|
-
})();
|
196
|
-
|
197
|
-
```
|
198
|
-
|
199
|
-
また上記では `Done.`という文字列を `resolve`の引数で返させました。
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/4/](https://jsfiddle.net/jun68ykt/bcm7jgzw/4/)
|
5
テキスト修正
test
CHANGED
@@ -158,15 +158,17 @@
|
|
158
158
|
|
159
159
|
() => {
|
160
160
|
|
161
|
+
if (wordArray.length > 0) {
|
162
|
+
|
161
|
-
printTarget.textContent += wordArray
|
163
|
+
printTarget.textContent += wordArray.shift();
|
162
|
-
|
164
|
+
|
163
|
-
|
165
|
+
} else {
|
164
166
|
|
165
167
|
clearInterval(intervalId);
|
166
168
|
|
167
|
-
resolve('Done.');
|
169
|
+
resolve('Done.');
|
168
|
-
|
170
|
+
|
169
|
-
}
|
171
|
+
}
|
170
172
|
|
171
173
|
}, 200);
|
172
174
|
|
@@ -194,8 +196,8 @@
|
|
194
196
|
|
195
197
|
```
|
196
198
|
|
197
|
-
上記では `Done.`という文字列を `resolve`の引数で返させました。
|
199
|
+
また上記では `Done.`という文字列を `resolve`の引数で返させました。
|
198
|
-
|
199
|
-
|
200
|
-
|
200
|
+
|
201
|
+
|
202
|
+
|
201
|
-
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/
|
203
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/4/](https://jsfiddle.net/jun68ykt/bcm7jgzw/4/)
|
4
テキスト修正
test
CHANGED
@@ -194,7 +194,7 @@
|
|
194
194
|
|
195
195
|
```
|
196
196
|
|
197
|
-
上記では `Done.`という文字列を `resole`の引数で返させました。
|
197
|
+
上記では `Done.`という文字列を `resolve`の引数で返させました。
|
198
198
|
|
199
199
|
|
200
200
|
|
3
テキスト修正
test
CHANGED
@@ -131,3 +131,71 @@
|
|
131
131
|
|
132
132
|
|
133
133
|
以上、参考になれば幸いです。
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
### 追記
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
別のやり方として、「200ミリ秒間隔で各文字を追加するのを、最後の文字まで行う」という処理をひとつの Promise にする方法もあります。この場合は Promise.all は使わず、以下のようになります。
|
142
|
+
|
143
|
+
```javascript
|
144
|
+
|
145
|
+
const addTypingMovement = (word, target) => {
|
146
|
+
|
147
|
+
const wordArray = [...word];
|
148
|
+
|
149
|
+
const printTarget = document.querySelector(target);
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
return new Promise(resolve => {
|
154
|
+
|
155
|
+
let i = 0;
|
156
|
+
|
157
|
+
const intervalId = setInterval(
|
158
|
+
|
159
|
+
() => {
|
160
|
+
|
161
|
+
printTarget.textContent += wordArray[i ++];
|
162
|
+
|
163
|
+
if (i === wordArray.length) {
|
164
|
+
|
165
|
+
clearInterval(intervalId);
|
166
|
+
|
167
|
+
resolve('Done.');
|
168
|
+
|
169
|
+
}
|
170
|
+
|
171
|
+
}, 200);
|
172
|
+
|
173
|
+
});
|
174
|
+
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
const finishTitleCall = (message) => {
|
180
|
+
|
181
|
+
document.querySelector('#result').textContent = message;
|
182
|
+
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
(async () => {
|
188
|
+
|
189
|
+
const message = await addTypingMovement('Hello World.', '#typing');
|
190
|
+
|
191
|
+
finishTitleCall(message);
|
192
|
+
|
193
|
+
})();
|
194
|
+
|
195
|
+
```
|
196
|
+
|
197
|
+
上記では `Done.`という文字列を `resole`の引数で返させました。
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/08axgkho/16/](https://jsfiddle.net/jun68ykt/08axgkho/16/)
|
2
テキスト修正
test
CHANGED
@@ -126,7 +126,7 @@
|
|
126
126
|
|
127
127
|
```
|
128
128
|
|
129
|
-
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/2
|
129
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/25/](https://jsfiddle.net/jun68ykt/6wsp3onu/25/)
|
130
130
|
|
131
131
|
|
132
132
|
|
1
テキスト修正
test
CHANGED
@@ -67,3 +67,67 @@
|
|
67
67
|
|
68
68
|
|
69
69
|
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/6/](https://jsfiddle.net/jun68ykt/6wsp3onu/6/)
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
上記のコードで、Promiseの配列を作るところの for文を [map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) を使って書き換え、 すべての文字が `target` に追加されたら、Done を表示するために `async`, `await` を使った例が以下です。
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
```javascript
|
78
|
+
|
79
|
+
const addTypingMovement = (word, target) => {
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
const printTarget = document.querySelector(target);
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
return [...word].map((char, i) => new Promise(
|
88
|
+
|
89
|
+
resolve => {
|
90
|
+
|
91
|
+
setTimeout(() => {
|
92
|
+
|
93
|
+
printTarget.textContent += char;
|
94
|
+
|
95
|
+
resolve();
|
96
|
+
|
97
|
+
}, i * 200);
|
98
|
+
|
99
|
+
})
|
100
|
+
|
101
|
+
);
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
}
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
const finishTitleCall = () => {
|
110
|
+
|
111
|
+
document.querySelector('#result').textContent = 'Done.';
|
112
|
+
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
(async () => {
|
118
|
+
|
119
|
+
await Promise.all(addTypingMovement('Hello World.', '#typing'));
|
120
|
+
|
121
|
+
finishTitleCall();
|
122
|
+
|
123
|
+
})();
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
```
|
128
|
+
|
129
|
+
- **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/24/](https://jsfiddle.net/jun68ykt/6wsp3onu/24/)
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
以上、参考になれば幸いです。
|