質問するログイン新規登録

回答編集履歴

1

校生

2019/02/28 11:11

投稿

miyabi-sun
miyabi-sun

スコア21553

answer CHANGED
@@ -5,19 +5,20 @@
5
5
 
6
6
  ブラウザに搭載されているJavaScriptと共通の話ですが、
7
7
  JSはシングルスレッドで動作します。
8
- JSの実行中はブラウザの応答が完全に止る仕様になっているためスリープみたいなことは実現不可能です。
8
+ JSの実行中はブラウザの応答が完全に止る仕様であるためスリープみたいなことは実現不可能です。
9
- とにかくさっさと実行して終わらなければならない
9
+ とにかくさっさと実行して終了さる必要がある
10
10
 
11
+ しかし、そこで壁になるのがI/O処理です。
11
- しかし、そこで壁になるのがI/O処理、ファイルの読み書きネットワークのリクエストは処理にいくら時間がかかるのか読めない部分があります。
12
+ ファイルの読み書きネットワークのリクエスト……といった事は処理にいくら時間がかかるのか読めない部分があります。
12
- Ajaxの為にHTTPリクエスト投げた瞬間ブラウザが操作を受け付けないとかユーザビリティ糞じゃん。
13
+ Ajaxの為にHTTPリクエスト投げた瞬間ブラウザが固まるとかユーザビリティ糞じゃん。
13
14
 
14
15
  そこで、JSはイベント駆動という考え方をします。
16
+ ブラウザが用意している「イベント置き場」というのがありまして、
15
- ブラウザが用意した「イベント置き場」というのがありまして、そこに「イベント完了条件」と「実行したい内容の関数」をセットで入れます。
17
+ そこに「イベント完了条件」と「実行したい内容の関数」をセットで登録します。
16
- このようにイベント登録を行います。
17
18
 
18
- ブラウザの中では無数のイベントが飛び交っています。
19
+ ブラウザでは無数のイベントが飛び交っています。
19
20
  「マウスカーソルが動いた時」「HTTP通信が完了した時」「マウスで何かの要素をクリックした時」
20
- このイベントの通知確認ながら、完了したイベントを巡回して、関数を取り出して実行という事を行っています。
21
+ ブラウザは絶えずイベント置き場巡回ており、完了したイベントが見つかり次第対応する関数を実行という事を行っています。
21
22
 
22
23
  質問文のコードで解説します。
23
24
 
@@ -31,26 +32,42 @@
31
32
  get_user_name関数を発火させた時、
32
33
  第二引数で「終わったら実行して欲しい関数」をコールバックとして渡しています。
33
34
  get_user_nameの中身はrequestによりHTTPリクエストを発射しているはずなので、
34
- 待ちぼうけするには長いので、そのコールバック関数はそのまんまイベント完了時に実行される関数の所ぶら下げ、そのまま「イベント登録終わったから俺終わっちゃおう」と終了します。
35
+ 待ちぼうけするには長いので、そのコールバック関数はそのまんまイベント完了時に実行される関数に登録します。
36
+ そのまま「イベント登録終わったから次いこう」と関数の処理が終わります。
35
37
 
36
- つまり、コールバック関数が実行されて`result_txt`変数の中身が書き換わるより前に、
37
- `console.log(result_txt);`が実行される仕組みになっています。
38
+ イベントの巡回&コールバック関数を取り出して実行されるタイミングは、
39
+ JSの実行が全て完了して暇になってからです。
38
40
 
41
+ なので、例えローカルマシン内で次の行が実行される前に結果を受け取ったとしても、
42
+ 質問文のコードでは先に`console.log(result_txt);`が実行されます。
43
+ 終わって暇になり、イベントの巡回を待ってからコールバック関数が実行されて`result_txt`変数の中身が書き換わります。
44
+
39
45
  この辺が非同期処理の仕組みになっています。
40
46
  解決法は単純、「コールバック関数の中身で後続のやりたい処理を全部書け」
41
- 中々クレイジーで
47
+ 何の解決にもなりませんが、こうれば使えます
42
48
 
49
+ ```JavaScript
50
+ get_user_name(options,function (error, respinse,body ){
51
+ result_txt=(body.user.profile.display_name).toString;
43
- こうして非同期処理でやりたい事が増えれば増える程、
52
+ console.log(result_txt);
53
+ })
44
- ネストが深くなり糞みたいなコードになってしまいます。
54
+ ```
45
55
 
46
- これがコールバック地獄」と呼ばれるものです。
56
+ 後続やりたい処理を全部書け」って中々クレイジーです
57
+ 非同期処理でやりたい事が増えれば増える程ネストが深くなり糞みたいなコードになります。
47
58
 
59
+ これを「コールバック地獄」と呼びます。
60
+
48
61
  ---
49
62
 
50
63
  > 何か対策はないの?
51
64
 
65
+ ベストプラクティスを紹介します。
66
+
52
- ちょっと仕様が難解ですが、今の所のベストプラクティスはPromiseを覚えて使いましょう。
67
+ まずはPromiseを覚えて使いましょう。
68
+ ある程度使いこなせるようになったらasync/awaitという構文を覚えましょう。
69
+
53
- また、async/awaitというPromiseを良い感じに扱う糖衣構文がありますので、
70
+ async/awaitPromiseを良い感じに扱う糖衣構文で、
54
71
  ここまで学習が進めば非同期処理は全く怖くありません。
55
72
 
56
73
  実は今回使っているrequestモジュールですが、これのPromise版があります。