回答編集履歴

3

更にmapとasyncのあわせ技を追記

2017/02/13 08:01

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -88,7 +88,7 @@
88
88
 
89
89
  // 全部コールバックの関数にしてしまう
90
90
 
91
- getTokens = tokens.map(function(apiTokens){
91
+ getTokens = apiTokens.map(function(apiToken){
92
92
 
93
93
  return function(next){
94
94
 
@@ -175,3 +175,95 @@
175
175
  // 1
176
176
 
177
177
  ```
178
+
179
+
180
+
181
+ ---
182
+
183
+
184
+
185
+ 更に追記:mapとasyncを併用して可変の要素を順番に実行
186
+
187
+ [async.series](http://caolan.github.io/async/docs.html#series)のページを見ると捗りそうですのでリンクを貼ります。
188
+
189
+
190
+
191
+ ```JavaScript
192
+
193
+ var functions = [
194
+
195
+ function (callback) { callback null, 1; },
196
+
197
+ function (callback) { callback null, 2; }
198
+
199
+ ];
200
+
201
+ async.series(functions, function(err, results){
202
+
203
+ console.log(results);
204
+
205
+ // [1, 2]
206
+
207
+ });
208
+
209
+ ```
210
+
211
+
212
+
213
+ これの仕組みを応用して作ったのが上記コードです(一部Typoがあったので修正済)
214
+
215
+ apiToken変数を束縛しながら、async.seriesが望むコールバック関数を持つ配列に加工しています。
216
+
217
+
218
+
219
+ ```JavaScript
220
+
221
+ getTokens = apiTokens.map(function(apiToken){
222
+
223
+ return function (callback) {
224
+
225
+ // apiTokenを利用してSlackと通信
226
+
227
+ callback null, 「通信結果」;
228
+
229
+ }
230
+
231
+ })
232
+
233
+
234
+
235
+ console.log(getTokens);
236
+
237
+ // [
238
+
239
+ // function (callback) { callback null, 「通信結果1」; },
240
+
241
+ // function (callback) { callback null, 「通信結果2」; },
242
+
243
+ // function (callback) { callback null, 「通信結果3」; },
244
+
245
+ // function (callback) { callback null, 「通信結果4」; },
246
+
247
+ // function (callback) { callback null, 「通信結果5」; }
248
+
249
+ // ]
250
+
251
+
252
+
253
+ async.series(getTokens, function(err, results){
254
+
255
+ console.log(results);
256
+
257
+ // [「通信結果1」, 「通信結果2」, 「通信結果3」, 「通信結果4」, 「通信結果5」]
258
+
259
+ });
260
+
261
+ ```
262
+
263
+
264
+
265
+ ※このやり方はあくまで発展途上のものの一つです。
266
+
267
+  なので動作確認後、必ず他の回答者さんの答えや
268
+
269
+  [JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版](http://qiita.com/gaogao_9/items/5417d01b4641357900c7)の記事を読んで上手いやり方を模索してみてください。

2

何故駄目なのかを追記しました。

2017/02/13 08:01

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -1,3 +1,55 @@
1
+ (追記)何故駄目なのかを追記しました。
2
+
3
+
4
+
5
+ > forEachの中では問題なくconsole.logで出力出来ているのですが、forEachを出てしまうと、下記コード内jsonTeamが出力出来なくなってしまっています。
6
+
7
+
8
+
9
+ `forEach`では解決出来ません。
10
+
11
+ Node.jsのコールバック周りの仕様を把握しましょう。
12
+
13
+
14
+
15
+ ざっくり解説すると、Node.jsやJavaScriptは元々シングルスレッドなのでHTTP通信等の他にボトルネックのある作業中はリソースの無駄ですよね。
16
+
17
+ それは嫌なので、通信系のメソッドにはコールバック関数を設定して、
18
+
19
+ 「通信終わったら、引数として渡しておいたこの関数実行しといてね。それじゃ俺は下の処理を実行するから〜」
20
+
21
+ …という命令を出した後、通信の結果を待たずに下の行の処理を実行し始めます。
22
+
23
+
24
+
25
+ この仕様により、例えば5箇所のAPIにリクエストを投げて、
26
+
27
+ その結果を配列で受け取るというのは普通のfor文では不可能です。
28
+
29
+ 5個のリクエストを同時に発射してそのまま下の行を実行するので、下の方で`console.log(jsonTeam);`とすると空の配列になってしまうのです。
30
+
31
+
32
+
33
+ なので、普通にやった場合、
34
+
35
+ 1回目のリクエストのコールバックに2回目のリクエストを発射するという風に、
36
+
37
+ 関数を5重にネストして、その後のコールバック関数内で`console.log(jsonTeam);`とすれば要素がちゃんと5つ入った配列を取得出来るのですが、
38
+
39
+ そんなことしたくないですよね…?
40
+
41
+
42
+
43
+ 5リクエストが固定ならまだしも、4つや6つに増えたり減ったりする場合また書き直しかよ…
44
+
45
+ というわけで、何かしらの特殊なラッパーが必要になります。
46
+
47
+
48
+
49
+ ---
50
+
51
+
52
+
1
53
  [JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版](http://qiita.com/gaogao_9/items/5417d01b4641357900c7)
2
54
 
3
55
  これは目を通してください。

1

mapとコード部分に追記しました。

2017/02/13 07:25

投稿

miyabi-sun
miyabi-sun

スコア21158

test CHANGED
@@ -14,6 +14,12 @@
14
14
 
15
15
  ```JavaScript
16
16
 
17
+ var http = require('http');
18
+
19
+ var https = require('https');
20
+
21
+ var Slack = require('slack-node');
22
+
17
23
  var async = require("async");
18
24
 
19
25
 
@@ -21,6 +27,10 @@
21
27
  var apiTokens = [], getTokens;
22
28
 
23
29
  // apiTokens.push(xxx);を繰り返す
30
+
31
+
32
+
33
+ console.log('start');
24
34
 
25
35
 
26
36
 
@@ -34,9 +44,15 @@
34
44
 
35
45
  slack.api("team.info", function(err, response) {
36
46
 
37
- // 略
47
+ delete(response.team.email_domain);
38
48
 
49
+ var icon = response.team.icon.image_original;
50
+
51
+ delete(response.team.icon);
52
+
53
+ response['team']['icon'] = icon;
54
+
39
- next err, result;
55
+ next err, response.team;
40
56
 
41
57
  })
42
58
 
@@ -46,12 +62,64 @@
46
62
 
47
63
 
48
64
 
49
- async.series(getTokens, function(err, results){
65
+ // 第二引数の関数の第二引数に、上のnextの第二引数の配列が入ってくる。
50
66
 
51
- // 上記のnextの第二引数を集約した配列がresultsになる
67
+ async.series(getTokens, function(err, Teams){
52
68
 
53
- // 全て完了後の処理
69
+ console.log(JSON.stringify(Teams, null, 2));
54
70
 
55
71
  })
56
72
 
57
73
  ```
74
+
75
+
76
+
77
+ ---
78
+
79
+
80
+
81
+ 追記
82
+
83
+
84
+
85
+ [Array.map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)はMDNにあるリスト操作系のメソッドです。
86
+
87
+ 配列の全ての要素に同じ処理を適用したものを返します。
88
+
89
+
90
+
91
+ forEachとは同じリスト操作系メソッドの兄弟みたいなものですが、forEachはサブルーチンなので処理した結果は捨てられます。
92
+
93
+ mapは処理した結果を戻り値として持ち帰って来ますので、特性からふさわしい方を使いわける事が一般的です。
94
+
95
+
96
+
97
+ ```JavaScript
98
+
99
+ var add_1 = function(it){ return it + 1; };
100
+
101
+ [1, 2, 3, 4, 5].map(add_1);
102
+
103
+ // [2, 3, 4, 5, 6]
104
+
105
+
106
+
107
+ var fns = [1, 2, 3, 4, 5].map(function(it){
108
+
109
+ return function(){
110
+
111
+ console.log(it);
112
+
113
+ };
114
+
115
+ });
116
+
117
+ // [fn, fn, fn, fn, fn]
118
+
119
+
120
+
121
+ fns[0]();
122
+
123
+ // 1
124
+
125
+ ```