回答編集履歴

4

文章訂正

2018/04/18 04:09

投稿

KSwordOfHaste
KSwordOfHaste

スコア18392

test CHANGED
@@ -80,7 +80,7 @@
80
80
 
81
81
  ---
82
82
 
83
- 追記: Javascriptで書いた部分は(Workerを使って意識的に非同期なスレッドで行わない限り)必ず同期的に行われます。Promiseは**非同期に何かをしてくれる機構ではなく**、非同期に行われる処理が完了してから次のことをするための**同期機構にしか過ぎない**ということがわかぁと思いま
83
+ 追記: Javascriptで書いた部分は(Workerを使って意識的に非同期なスレッドで行わない限り)必ず同期的に行われます。Promiseは**非同期に何かをしてくれる機構ではなく**、非同期に行われる処理が完了してから次のことをするための**同期機構にしか過ぎない**ということが伺えよう例を書てみした
84
84
 
85
85
 
86
86
 

3

例を追加

2018/04/18 04:09

投稿

KSwordOfHaste
KSwordOfHaste

スコア18392

test CHANGED
@@ -75,3 +75,213 @@
75
75
  ---
76
76
 
77
77
  追記:短く書くためにES2015で書いてます。最初の回答で`var f = (to) => {...}`としましたが特に意図あってのことではなかったのでfを普通のfunction定義に置き換えました。
78
+
79
+
80
+
81
+ ---
82
+
83
+ 追記: Javascriptで書いた部分は(Workerを使って意識的に非同期なスレッドで行わない限り)必ず同期的に行われます。Promiseは**非同期に何かをしてくれる機構ではなく**、非同期に行われる処理が完了してから次のことをするための**同期機構にしか過ぎない**ということがわかるかなぁと思います。
84
+
85
+
86
+
87
+ ```javascript
88
+
89
+ const t0 = +new Date()
90
+
91
+
92
+
93
+ function log(msg) {
94
+
95
+ const elapsed = " " + (+new Date() - t0)
96
+
97
+ const prefix = elapsed.slice(elapsed.length - 4)
98
+
99
+ console.log(`${prefix}: ${msg}`)
100
+
101
+ }
102
+
103
+
104
+
105
+ function f(msg, sy, to) {
106
+
107
+ log(`invoked ${msg}(${sy} ${to})`)
108
+
109
+ return new Promise((resolve, reject) => {
110
+
111
+ if (sy == 'sync') {
112
+
113
+ const start = +new Date()
114
+
115
+ do {} while (+new Date() - start <= to)
116
+
117
+ doResolve()
118
+
119
+ } else {
120
+
121
+ setTimeout(() => doResolve(), to)
122
+
123
+ }
124
+
125
+
126
+
127
+ function doResolve() {
128
+
129
+ resolve(`${msg} ${sy} ${to}`)
130
+
131
+ log(`resolved ${msg} ${sy} ${to}`)
132
+
133
+ }
134
+
135
+ })
136
+
137
+
138
+
139
+ }
140
+
141
+
142
+
143
+ function done(r) {
144
+
145
+ log(`promise chain done ${r}`)
146
+
147
+ }
148
+
149
+
150
+
151
+ f('A', 'async', 0).then(r => f(`${r}->then`, 'async', 0)).then(done)
152
+
153
+ f('B', 'async', 0).then(r => f(`${r}->then`, 'async', 0)).then(done)
154
+
155
+ f('C', 'async', 100).then(r => f(`${r}->then`, 'async', 200)).then(done)
156
+
157
+ f('D', 'async', 200).then(r => f(`${r}->then`, 'async', 100)).then(done)
158
+
159
+ f('--', 'async', 1000)
160
+
161
+ .then(r => {
162
+
163
+ f('A', 'sync', 0).then(r => f(`${r}->then`, 'sync', 0)).then(done)
164
+
165
+ f('B', 'sync', 0).then(r => f(`${r}->then`, 'sync', 0)).then(done)
166
+
167
+ f('C', 'sync', 100).then(r => f(`${r}->then`, 'sync', 200)).then(done)
168
+
169
+ f('D', 'sync', 200).then(r => f(`${r}->then`, 'sync', 100)).then(done)
170
+
171
+ })
172
+
173
+ ```
174
+
175
+ 結果
176
+
177
+ ```text
178
+
179
+ 1: invoked A(async 0)
180
+
181
+ 2: invoked B(async 0)
182
+
183
+ 2: invoked C(async 100)
184
+
185
+ 2: invoked D(async 200)
186
+
187
+ <--本来の非同期処理の場合、非同期処理の起動は一気に行われる
188
+
189
+ 2: invoked --(async 1000)
190
+
191
+ 2: resolved A async 0
192
+
193
+ 2: resolved B async 0
194
+
195
+ 2: invoked A async 0->then(async 0)
196
+
197
+ 2: invoked B async 0->then(async 0)
198
+
199
+ 2: resolved A async 0->then async 0
200
+
201
+ 2: resolved B async 0->then async 0
202
+
203
+ 2: promise chain done A async 0->then async 0
204
+
205
+ 2: promise chain done B async 0->then async 0
206
+
207
+ <--C/Dなど時間がかかる処理があってもそれを非同期に行いさえすればA/BはC/Dの完了前に完了する
208
+
209
+ <--これはPromiseによる恩恵ではない。A/B/C/Dの処理(setTimeout)が非同期であることがポイント
210
+
211
+ 112: resolved C async 100
212
+
213
+ 112: invoked C async 100->then(async 200)
214
+
215
+ 206: resolved D async 200
216
+
217
+ 206: invoked D async 200->then(async 100)
218
+
219
+ 315: resolved D async 200->then async 100
220
+
221
+ 315: promise chain done D async 200->then async 100
222
+
223
+ 315: resolved C async 100->then async 200
224
+
225
+ 315: promise chain done C async 100->then async 200
226
+
227
+ 1008: resolved -- async 1000
228
+
229
+ 1008: invoked A(sync 0)
230
+
231
+ 1024: resolved A sync 0
232
+
233
+ 1024: invoked B(sync 0)
234
+
235
+ 1039: resolved B sync 0
236
+
237
+ 1039: invoked C(sync 100)
238
+
239
+ 1149: resolved C sync 100
240
+
241
+ 1149: invoked D(sync 200)
242
+
243
+ <-- Cは同期的に(ビジーループで)100ms消費するためDはその後に起動される(全然非同期でない)
244
+
245
+ 1359: resolved D sync 200
246
+
247
+ 1359: invoked A sync 0->then(sync 0)
248
+
249
+ <-- C,Dが同期的に300ms処理しているためAがとっくに終わっていても
250
+
251
+ A/Bのthen部分はC/Dの起動後にしか動けない
252
+
253
+ 1375: resolved A sync 0->then sync 0
254
+
255
+ 1375: invoked B sync 0->then(sync 0)
256
+
257
+ 1391: resolved B sync 0->then sync 0
258
+
259
+ 1391: invoked C sync 100->then(sync 200)
260
+
261
+ 1594: resolved C sync 100->then sync 200
262
+
263
+ 1594: invoked D sync 200->then(sync 100)
264
+
265
+ <-- Dのthen部分は1359ms後にresolveされている。しかしCのthen部分を同期的に処理しているため
266
+
267
+ それが終わらないとDのthen部分が起動できない
268
+
269
+ Dのthen部分はresolveされてから250msも後になってからでないと起動されない(全然非同期でない)
270
+
271
+ 1703: resolved D sync 200->then sync 100
272
+
273
+ 1703: promise chain done A sync 0->then sync 0
274
+
275
+ 1703: promise chain done B sync 0->then sync 0
276
+
277
+ 1703: promise chain done C sync 100->then sync 200
278
+
279
+ 1703: promise chain done D sync 200->then sync 100
280
+
281
+ <-- 肝心の処理が同期的になっているとPromiseを使ってもなんら意味がない
282
+
283
+ A-Bの処理が全て終わってからでないとpromise chainが完了しないことからもそれがわかる
284
+
285
+ ```
286
+
287
+ Javascriptで記述するのは「非同期処理を起動するのに必要なパラメーター計算と非同期処理の起動」「非同期処理が完了した際に結果を料理すること」であり、どちらも一瞬で終わるべき処理内容とするのが普通だと思います。それは基本的に非同期APIを用いて論理を書くからです。もし同期APIを用いて逐次的に処理するような機能を並行して動かしたいのならthink49さんが回答しておられるようにWorkerのようなマルチスレッド機構を用いることになると思います。

2

コードミス

2018/04/18 04:07

投稿

KSwordOfHaste
KSwordOfHaste

スコア18392

test CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  ```javascript
26
26
 
27
- function f(to) => {
27
+ function f(to) {
28
28
 
29
29
  return new Promise((resolve, reject) => {
30
30
 

1

ES2015に統一

2018/04/17 10:54

投稿

KSwordOfHaste
KSwordOfHaste

スコア18392

test CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  ```javascript
26
26
 
27
- var f = (to) => {
27
+ function f(to) => {
28
28
 
29
29
  return new Promise((resolve, reject) => {
30
30
 
@@ -69,3 +69,9 @@
69
69
  100
70
70
 
71
71
  150
72
+
73
+
74
+
75
+ ---
76
+
77
+ 追記:短く書くためにES2015で書いてます。最初の回答で`var f = (to) => {...}`としましたが特に意図あってのことではなかったのでfを普通のfunction定義に置き換えました。