回答編集履歴
1
校生
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
67
|
+
まずはPromiseを覚えて使いましょう。
|
|
68
|
+
ある程度使いこなせるようになったらasync/awaitという構文を覚えましょう。
|
|
69
|
+
|
|
53
|
-
|
|
70
|
+
async/awaitはPromiseを良い感じに扱う糖衣構文で、
|
|
54
71
|
ここまで学習が進めば非同期処理は全く怖くありません。
|
|
55
72
|
|
|
56
73
|
実は今回使っているrequestモジュールですが、これのPromise版があります。
|