回答編集履歴

5

追記部分への対応

2018/12/15 04:55

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -175,3 +175,255 @@
175
175
  }
176
176
 
177
177
  ```
178
+
179
+
180
+
181
+ ---
182
+
183
+
184
+
185
+ 【追記箇所への回答】
186
+
187
+
188
+
189
+ > 1.staticなメソッドをasyncさせる方法はないのでしょうか?
190
+
191
+
192
+
193
+ まぁ、参考書とかもないですし情報少なくて辛いですよね。
194
+
195
+ これを参考にしてみてください。
196
+
197
+
198
+
199
+ ※await構文の右辺がPromiseの場合、実行してresolve(value)のvalue部分を取り出しますが、String等の値であればそれをそのまま利用しようとします。
200
+
201
+
202
+
203
+ ```JavaScript
204
+
205
+ class Animal {
206
+
207
+ static async meow () {
208
+
209
+ return await 'meow!'
210
+
211
+ }
212
+
213
+ }
214
+
215
+ Animal.meow().then(console.log);
216
+
217
+ // "meow!"が出力される
218
+
219
+ ```
220
+
221
+
222
+
223
+ > 2.以下のvalidateRegisterUsersData()のようなPromiseチェーンを組むときに3変数になってしまうのですが、isFilledUsernameの引数をusernameだけにしてもPromiseチェーンは組めるのでしょうか?
224
+
225
+
226
+
227
+ できる or できないで言えばできます。
228
+
229
+ Promiseのreslve関数を実行するときの書式で、`resolve(1, 2, 3)`という風に3つの引数で実行した場合、
230
+
231
+ `.then((a, b, c) => console.log(a, b, c))`という風に3つの引数で受けることが可能です。
232
+
233
+
234
+
235
+ ただし、async / await構文で戻って来る場合、resolveの第一引数しか持って帰れません。
236
+
237
+ Promise返す関数は最小の挙動を記述すれば、そんなにたくさんの引数を持って帰りたいという要求は出るはずがありません。
238
+
239
+
240
+
241
+ > 3.以下の2点を守ってコードを書き換える際に、Promiseチェーンを組むときは以下のような形になると思ったのですが、間違ってますか?
242
+
243
+
244
+
245
+ そもそもの話で、Promiseが必要な関数/メソッドってどういうものだと思いますか?
246
+
247
+ それは「非同期処理であるべきもの」だけです。
248
+
249
+
250
+
251
+ 非同期処理であるべきものとは何でしょうか?
252
+
253
+ それは主に「HDDに問い合わせる」「ネットワーク越しに問い合わせる」といった、メモリに保存済みのものを呼び出すものより圧倒的に遅いものがその対象になるべきです。
254
+
255
+
256
+
257
+ > ```JavaScript
258
+
259
+ > static __isFilledPassword(password, isValidated, errors) {
260
+
261
+ > new Promise((resolve, reject) => {
262
+
263
+ > isValidated = false;
264
+
265
+ > errors.password = "passwordが未入力です。";
266
+
267
+ > });
268
+
269
+ > }
270
+
271
+ > ```
272
+
273
+
274
+
275
+ passwordが変数が空か否かを確認するメソッドは非同期処理であるべきか?
276
+
277
+ と聞かれれば、別にHDDやネットワーク越しに問い合わせるわけではないので不要です。
278
+
279
+
280
+
281
+ 要するにお前Promiseである必要ないじゃんって話ですし、
282
+
283
+ isFilledPasswordというメソッド/関数ならば、普通のエンジニアはtrue or falseが帰って来ることを想定するはずです。
284
+
285
+ この辺のメソッド名の名付けや挙動は英語力も必要になってきます。
286
+
287
+
288
+
289
+ Authenticatorクラスの中の話なので、例えばinvalidReasonsという配列が帰ってきそうなメソッド名にしてはいかが?
290
+
291
+ 配列が空、つまり`reasons.length === 0`がtrueならば妥当なデータ、falseならば不正な値というわけです。
292
+
293
+ これなら死ぬほど使いやすくなったと思いませんか?
294
+
295
+
296
+
297
+ ```JavaScript
298
+
299
+ class Authenticator {
300
+
301
+ static invalidReasons({username, password}) {
302
+
303
+ const reasons = [];
304
+
305
+ if (username === '') {
306
+
307
+ reasons.push('usernameが未入力です');
308
+
309
+ }
310
+
311
+ if (password === '') {
312
+
313
+ reasons.push('passwordが未入力です。');
314
+
315
+ }
316
+
317
+ return reasons;
318
+
319
+ }
320
+
321
+ }
322
+
323
+ ```
324
+
325
+
326
+
327
+ > `isValidated = false;`
328
+
329
+
330
+
331
+ 細かいですが、こういう使い方はバグの原因なので極力やめてください。
332
+
333
+ こういう使い方する関数を「副作用がある関数」と呼び、一定以上の技量のエンジニアには嫌われる使い方です。
334
+
335
+ パフォーマンス改善のテクニックの一つではあるのですが、これを意識せず使いまくったシステムだと単純にバグの量が100倍増えるでしょう、それだけのコストを払う意味があるケースは実際殆ど存在せず禁じ手になっています。
336
+
337
+
338
+
339
+ また、今回の用途では正しく動作しません。
340
+
341
+ 何故かというとString、Number、Booleanなどのプリミティブ値は値渡しなので、関数の内側で引数として宣言したisValidated変数の内容は変わりますが、引数として渡した外側の世界の変数には影響しません。
342
+
343
+
344
+
345
+ ```JavaScript
346
+
347
+ var add3 = it => {
348
+
349
+ it += 3;
350
+
351
+ return it;
352
+
353
+ }
354
+
355
+ var a = 1;
356
+
357
+ console.log(add3(a)); // 4
358
+
359
+ console.log(a); // 1
360
+
361
+ ```
362
+
363
+
364
+
365
+ オブジェクトや配列等のオブジェクト系はJavaScriptでは一見参照渡しのように思えますが、
366
+
367
+ 実際には参照の値渡しなので、やはり束縛が切れるので無意味です。
368
+
369
+
370
+
371
+ ```JavaScript
372
+
373
+ var nameChange = (obj, name) => {
374
+
375
+ obj = {name};
376
+
377
+ return obj;
378
+
379
+ }
380
+
381
+ var taro = {name: 'taro'}
382
+
383
+ var jiro = nameChange(taro, 'jiro')
384
+
385
+ console.log(taro); // {name: 'taro'}
386
+
387
+ console.log(jiro); // {name: 'jiro'}
388
+
389
+
390
+
391
+ // 副作用を起こしたければこうする
392
+
393
+ var nameChange2 = (obj, name) => {
394
+
395
+ obj.name = name; // 変数への代入ではなく、プロパティを書き換えるような挙動にする
396
+
397
+ return obj;
398
+
399
+ }
400
+
401
+ var taro = {name: 'taro'}
402
+
403
+ var jiro = nameChange2(taro, 'jiro')
404
+
405
+ console.log(taro); // {name: 'jiro'} <- 副作用の再現に成功
406
+
407
+ console.log(jiro); // {name: 'jiro'}
408
+
409
+ ```
410
+
411
+
412
+
413
+ > // __isFilledUsername = username, isValidated, errors => new Promise() だとエラー
414
+
415
+
416
+
417
+ ES2015のクラス構文の書き方を復習しましょう
418
+
419
+ [クラス - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)
420
+
421
+
422
+
423
+ それと、アロー関数のルールで`username, isValidated, errors => new Promise()`のように引数が複数になる場合は引数の部分のカッコは省略できません。
424
+
425
+ アロー関数でカッコを省略できるのは引数が1個のケースだけです。
426
+
427
+
428
+
429
+ [アロー関数 - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

4

多分これで完成形

2018/12/15 04:55

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -120,7 +120,7 @@
120
120
 
121
121
  // 関数は外のbodyみたいな値に依存するのではなく、引数で受け付けたほうがいい
122
122
 
123
- const isUniqueUsername = (username) => new Promise((resolve, reject) => {
123
+ const isUniqueUsername = username => new Promise((resolve, reject) => {
124
124
 
125
125
  // usernameが空か否かはisUniqueで確認するべきじゃないので、バリデート関数を別途用意すべき
126
126
 
@@ -148,15 +148,7 @@
148
148
 
149
149
  // 余計な事はせずにやること終わったらさっさとtrue or false返して終了する
150
150
 
151
- if (results.length === 0) {
151
+ resolve(results.length === 0);
152
-
153
- resolve(true);
154
-
155
- } else {
156
-
157
- resolve(false);
158
-
159
- }
160
152
 
161
153
  });
162
154
 

3

更に修正

2018/12/14 09:44

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -122,25 +122,7 @@
122
122
 
123
123
  const isUniqueUsername = (username) => new Promise((resolve, reject) => {
124
124
 
125
- // 長いif文によネストは可読性を下げるので、ド節でぐ返す
125
+ // usernameが空か否かはisUniqueで確認すべきじゃないので、バリデト関数を別途用意べき
126
-
127
- if (!username) {
128
-
129
- // resolve(false)かreject(エラー理由)かは要検討
130
-
131
- resolve(false);
132
-
133
- return;
134
-
135
- }
136
-
137
- if (!password) {
138
-
139
- resolve(false);
140
-
141
- return;
142
-
143
- }
144
126
 
145
127
 
146
128
 
@@ -152,7 +134,7 @@
152
134
 
153
135
  }, (error, results, fields) => {
154
136
 
155
- // 余計な事せずにること終わったさっさとtrue or false返して終了する
137
+ // errorがnull以外の時、MySQLのコネクション失敗やらの申告なエラーなのでrejectで対応
156
138
 
157
139
  if (error) {
158
140
 
@@ -161,6 +143,10 @@
161
143
  return;
162
144
 
163
145
  }
146
+
147
+
148
+
149
+ // 余計な事はせずにやること終わったらさっさとtrue or false返して終了する
164
150
 
165
151
  if (results.length === 0) {
166
152
 

2

回答のコードがちょっと変だったので修正

2018/12/14 09:42

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -120,7 +120,7 @@
120
120
 
121
121
  // 関数は外のbodyみたいな値に依存するのではなく、引数で受け付けたほうがいい
122
122
 
123
- const isUsernameUnique = ({username, password}) => new Promise((resolve, reject) => {
123
+ const isUniqueUsername = (username) => new Promise((resolve, reject) => {
124
124
 
125
125
  // 長いif文によるネストは可読性を下げるので、ガード節ですぐ返す
126
126
 
@@ -148,7 +148,7 @@
148
148
 
149
149
  sql: "SELECT * FROM users WHERE username = ?;",
150
150
 
151
- values: [body.username]
151
+ values: [username]
152
152
 
153
153
  }, (error, results, fields) => {
154
154
 
@@ -182,9 +182,9 @@
182
182
 
183
183
  // bodyをどっから取ってくるかは知らんけどこんな感じ
184
184
 
185
- var isValidated = await isUsernameUnique(body);
185
+ var isUnique = await isUniqueUsername(body.username);
186
186
 
187
- if (isValidated) {
187
+ if (isUnique) {
188
188
 
189
189
  console.log('ユニークなIDです');
190
190
 

1

><

2018/12/14 09:39

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -83,6 +83,10 @@
83
83
  実際にこれを走らせるとthenの意味はまるでなくて、その場で全てのPromiseが同時に走るわ、引き継がせるデータがちゃんとリレー出来てないわという有様で、
84
84
 
85
85
  意図したように動かないんじゃないの?という印象ですね。
86
+
87
+
88
+
89
+ 特に設計思想としてはpromise走らせた結果として`resolve(isValided)`を実行しながら返すという設計にすべきで、予め`let isValided = true;`を実行しておいて、Promiseの中身で外のスコープの変数を書き換えてfalseにするのはお前Promiseの意味ないじゃんということで落第です。
86
90
 
87
91
 
88
92