前提・実現したいこと
node.jsを利用し、複数のチームのSlackからチャンネル情報を取得して、
全チャンネル(絞り込みは追って対応するとして)の最終投稿を取得したいと考えています。
それらを選別・整形し、最終的にはHTMLで出力することを想定しています。
試したこと
asyncを利用して書いたりした物の、どうしてもfor
やforEach
が発生し、
同期処理と非同期処理(で良いもの)が入り乱れ、
何をどうしたら正しく処理が進むのか解らなくなってきてしまっています。
APIの取得は完了を待たねばならず、その辺りの解消法が一番重要だと思っています。
個別に質問をして解消を...と思った物の、
複数のAPI呼び出しが1つのネックになっている事も踏まえ、まとめた形で改めて質問を
することにしました。
理想の流れとしては、
// ここからtokenの数だけ繰り返し
[API] 該当チームの情報取得
[API] 該当チームの全てのチャンネル情報を取得(プライベートチャンネルのみで良いのでgroupsが対象)
// ここからチャンネルの数だけ繰り返し
[API] 各チャンネルの最終投稿を取得
[API] 最終投稿のユーザ名などを取得
受け取ったユーザ名と投稿内容の結合
チャンネル情報と投稿の情報の結合
// ここまで
// ここまで
全てのデータの結合(やもすれば、繰り返しの中でpushする?)
該当のデータ絞り込み作業
HTMLに整形
だと思っています。
外部APIを利用するため、酷く躓いている気がするのですが、教えていただけたら幸いです。
2017/02/20追記
どこまでやってみたかという部分なのですが、
結局の所、繰り返した実行結果をループの外側に持ち出すことで問題が起きている印象です。
若干混乱しており、何が何だか...という状態になっていることも否めないのですが、
一番外側の繰り返しについては、取得結果を繰り返し利用することも無く、無事に取得して、次の処理に渡す事はできています。
問題は、その取得したグループ情報を1つずつやりくりし、全ての結果を拾って1つの配列にまとめるという部分かと思っています。
うまくお伝えできているかわからず恐縮ですが、コレで、少し伝わったでしょうか...。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
追記ありがとうございます。
頂いた内容を元に、やりたいと考えられているであろう内容を回答いたします。
配列データに対して非同期処理を回し、結果を配列にして返す
それぞれのグループ情報に対して非同期処理(今回はAPIを叩いてデータを取得する)を行い、
全ての結果を配列として格納するということなので、
var async = require("async");
var https = require("https");
var group = [
{"id":"hoge"},
{"id":"fuga"},
{"id":"piyo"}
];
// 配列のそれぞれのデータが data に格納される
async.map(group, (data, next) => {
// API を叩く
https.get("https://example.com/", (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
var json = JSON.parse(body);
// 各データについて、結果を格納
next(null, body.data);
});
});
}, (err, result) => {
// next の第二引数で渡した値が、配列になって result に入ってくる
console.log(result);
});
こんな感じになるのではと思います。
async
を使用されているということですので、 async.map
を使用しました。
これは、第一引数の配列データをそれぞれ第二引数の関数に渡し、
全てのデータに対して next
が実行された時点で
第三引数の result
にデータを配列にして入れてくれる、というものです。
今やりたいと思われていることと一致するのではないでしょうか。
非同期処理を直列に配置する
非同期処理と同期処理が混ざって混乱されている部分もあるようですので、
その部分についても私なりの解決法を提案いたします。
こちらも async
を利用されていますので、
async.waterfall
を使用されるのが良いかと思います。
var async = require("async");
var group = [
{"id":"hoge"},
{"id":"fuga"},
{"id":"piyo"}
];
async.waterfall([
(cb) => {
// 非同期処理
async.map(group, (data, next) => {
next(null, data.id);
}, (err, result) => {
cb(null, result)
});
},
(arg, cb) => {
// 同期処理
var sync = arg.map((data) => {
return data + "!!!";
});
cb(null, sync);
}
], (err, arg) => {
console.log(arg); // [ 'hoge!!!', 'fuga!!!', 'piyo!!!' ]
});
async.waterfall
は直列につなげた関数のコールバックに渡されたデータを、
次の関数で使用できる特徴があります。
ここで注意したいのは、(当然のことですが) async.waterfall
内での処理は
非同期処理を行う関数でなくとも良い点です。
それぞれの処理を(非同期・同期処理関係なく)関数にまとめて、
return
の代わりにコールバックを呼び出す形にすることで
簡単に直列に繋ぐことができ、見通しもよくなるのではと思います。
すでに流れとして、動作を部品ごとに分ける作業はされているようですので、
あとはそれぞれを async.waterfall
で繋ぐことで
期待する処理がかけるのではないでしょうか。
この回答で、お役に立てましたでしょうか。
もし、イメージされていることと異なっている場合は改めて追記いただくか、
新しく記事を立てていただけるとありがたいです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
ezaki
2017/02/18 23:32
前回のご質問も拝見しまして、非同期処理周りでお困りなのかな…と思いますが、どのような回答をお求めなのかがイマイチ掴みきれません。「ここまでできたがここからが分からない」ということを明確にすることは可能ですか?