回答編集履歴

9

テキスト修正

2019/10/12 19:52

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -160,7 +160,7 @@
160
160
 
161
161
 
162
162
 
163
- 上記の 1. と 2. とは異なり、「200ミリ秒間隔でひと文字ずつ、最後の文字まで表示する」という処理をひとつの Promise にすることもできます。この場合は Promise.all は使わず、以下のようになります。
163
+ 上記の 1. と 2. とは異なり、「200ミリ秒間隔でひと文字ずつ、最後の文字まで表示する」という処理をひとつの Promise にすることもできます。以下のそのコード例です。
164
164
 
165
165
  ```javascript
166
166
 
@@ -214,14 +214,20 @@
214
214
 
215
215
  ```
216
216
 
217
- また上記では `Done.`という文字列を `resolve`の引数で返させました。
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

テキスト修正

2019/10/12 19:52

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -160,27 +160,25 @@
160
160
 
161
161
 
162
162
 
163
- 上記の 1. と 2. とは異なり、「200ミリ秒間隔で文字を追加するのを、最後の文字まで行う」という処理をひとつの Promise にすることもできます。この場合は Promise.all は使わず、以下のようになります。
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
- const wordArray = [...word];
169
+ resolve => {
170
-
170
+
171
- const printTarget = document.querySelector(target);
171
+ const printTarget = document.querySelector(target);
172
-
173
-
174
-
172
+
175
- return new Promise(resolve => {
173
+ let i = 0;
176
174
 
177
175
  const intervalId = setInterval(
178
176
 
179
177
  () => {
180
178
 
181
- if (wordArray.length > 0) {
179
+ if (i < word.length) {
182
-
180
+
183
- printTarget.textContent += wordArray.shift();
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/5/](https://jsfiddle.net/jun68ykt/bcm7jgzw/5/)
221
+ - **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/14/](https://jsfiddle.net/jun68ykt/bcm7jgzw/14/)
224
222
 
225
223
 
226
224
 

7

テキスト修正

2019/10/12 19:42

投稿

jun68ykt
jun68ykt

スコア9058

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/4/](https://jsfiddle.net/jun68ykt/bcm7jgzw/4/)
223
+ - **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/5/](https://jsfiddle.net/jun68ykt/bcm7jgzw/5/)
226
224
 
227
225
 
228
226
 

6

テキスト修正

2019/10/12 18:32

投稿

jun68ykt
jun68ykt

スコア9058

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
- 上記のコードで、Promiseの配列を作るところの for文を [map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map) を使って書き換え、 すべての文字が `target` に追加されたら、Done を表示するために `async`, `await` を使った例が以下です。
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

テキスト修正

2019/10/12 18:23

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -158,15 +158,17 @@
158
158
 
159
159
  () => {
160
160
 
161
+ if (wordArray.length > 0) {
162
+
161
- printTarget.textContent += wordArray[i ++];
163
+ printTarget.textContent += wordArray.shift();
162
-
164
+
163
- if (i === wordArray.length) {
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/08axgkho/16/](https://jsfiddle.net/jun68ykt/08axgkho/16/)
203
+ - **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/bcm7jgzw/4/](https://jsfiddle.net/jun68ykt/bcm7jgzw/4/)

4

テキスト修正

2019/10/12 18:08

投稿

jun68ykt
jun68ykt

スコア9058

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

テキスト修正

2019/10/12 17:52

投稿

jun68ykt
jun68ykt

スコア9058

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

テキスト修正

2019/10/12 17:44

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -126,7 +126,7 @@
126
126
 
127
127
  ```
128
128
 
129
- - **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/24/](https://jsfiddle.net/jun68ykt/6wsp3onu/24/)
129
+ - **動作確認用 jsFiddle:** [https://jsfiddle.net/jun68ykt/6wsp3onu/25/](https://jsfiddle.net/jun68ykt/6wsp3onu/25/)
130
130
 
131
131
 
132
132
 

1

テキスト修正

2019/10/12 17:18

投稿

jun68ykt
jun68ykt

スコア9058

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
+ 以上、参考になれば幸いです。