質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

解決済

(Promise)直列処理の中でreduceを扱う事はできますか?

TEA
TEA

総合スコア0

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1回答

0評価

1クリップ

3435閲覧

投稿2016/06/10 08:41

編集2022/01/12 10:58

promiseの記述方法が正しいか分からなかったのでご質問させてください。環境はnode.js v4.3です。

promiseの直列処理のいくつかの処理の中で、配列要素を処理するreduceを追加することはできますか?また、2つ目の質問ですが、下記コード中のfunction taskB_Work(value)で記述する処理によっては、逐次処理が最後まで進むものの、プロセスが終了しない事がありました。これはどのような原因が考えられますでしょうか?(console.log("complete!");以下を参照)

主にこのような処理を逐次処理で行いたいと考えております。

  1. 配列を取得
  2. 配列要素を元に処理 (配列要素の数だけ逐次処理したい)
  3. 処理した結果を出力

現在、以下のようなコードを書いていますが、このような形でpromiseの記述は問題ないでしょうか?

参考記事: Qiita | Promiseについて0から勉強してみた
http://qiita.com/toshihirock/items/e49b66f8685a8510bd76

javascript

// 配列の取得を行うタスク function taskA() { return new Promise(function(resolve, reject) { var Arr = ["a","b","c","d","e"]; resolve(Arr); }); } // taskAで取得した値を加工するタスク function taskB(arr) { var editedArr = []; return new Promise(function(resolve, reject) { return arr.reduce(function(promise, value) { return promise.then(function() { return taskB_Work(value); }).then(function(editedElement){ editedArr.push(editedElement); }); }, Promise.resolve() ) .then( function(){ resolve(editedArr); }, function(){ reject("taskB 処理に失敗"); } ); }); } // taskBのreduceで呼び出され、配列要素に対して行う処理 function taskB_Work(value){ return new Promise(function(resolve, reject) { setTimeout(function () { console.log("[taskB_Work] value="+value); resolve(value + "_edited"); }, 2000); }); } // taskBで加工した配列の値を出力するタスク function taskC(editedArr) { return new Promise(function(resolve, reject) { console.log("[taskC]:"); console.log(editedArr); resolve(); }); } //逐次処理を行う function sequenceTasks(tasks) { function recordValue(results, value) { return value; } var pushValue = recordValue.bind(null, []); return tasks.reduce(function (promise, task) { return promise.then(task).then(pushValue); }, Promise.resolve()); } var promises = { doTaskA: function() { return taskA().then(); }, doTaskB: function(arr) { return taskB(arr).then(); }, doTaskC: function(editedArr) { return taskC(editedArr).then(); } }; function main() { return sequenceTasks([ promises.doTaskA, promises.doTaskB, promises.doTaskC ]); } main().then(function(value) { console.log("complete!"); //function taskB_Work(value)`で記述する処理によっては、逐次処理がここまで進むものの、プロセスが終了しない事があります。 }).catch(function(error) { console.log("error:" + error); });

taskB_Workの処理内容は実際には以下のようなものを考えています。改行区切りのURLが保存されているテキストファイルを開き(taskA)、taskBを実行後に、新たに取得したURLをテキストファイルで出力する(taskC)という処理です。

javascript

// flickrのリサイズ画像URL(inPhotoURL)を元に、オリジナルサイズの画像URLを取得する。 /* var FlickrAPI = require("flickrapi"); var flickrApiOptions = { api_key : process.env.api_key, secret : process.env.secret, permissions : process.env.permissions, user_id : process.env.user_id, access_token : process.env.access_token, access_token_secret: process.env.access_token_secret }; */ function taskB_Work(inPhotoURL){ return new Promise(function(resolve, reject) { FlickrAPI.authenticate(flickrApiOptions, function(error, flickr) { var matchPat = inPhotoURL.match(/(https:\/\/farm[0-9]\.staticflickr\.com\/[0-9]+\/)([0-9]+)_([0-9a-z]+)[0-9a-z_]*\.jpg/); var parameter = { "api_key" : flickrApiOptions.api_key , "photo_id" : matchPat[2], "secret" : matchPat[3] }; if(!error){ // getInfoにより、originalsecretとoriginalformatを取得 // (getInfo) https://www.flickr.com/services/api/flickr.photos.getInfo.html flickr.photos.getInfo(parameter, function(err, result) { if(err) { reject("flickr APIの実行に失敗しました : " + err); }else{ resolve(matchPat[1] + matchPat[2] + "_"+ result.photo.originalsecret +"_o."+ result.photo.originalformat); } }); }else{ reject("flickr APIの認証に失敗しました :" + error); } }); }); }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

horse_n_deer
horse_n_deer

2016/06/10 23:05

関数外で状態を保持する意味はありますか?もし、module.exportsなどで関数を提供している場合、複数回の同時実行でArr_editedが壊れると思いますが…。
TEA
TEA

2016/06/13 08:04

ご指摘ありがとうございます。状態とは具体的に、配列の値のことでしょうか?関数外で状態を保持する理由は特にありません。promiseの返り値をどのように渡せばいいのか不明でした(特に関数taskB)ので、自分なりに理解できるコードを記述させて頂きました。 指摘後、配列については関数内で定義するよう変更してみました。こちらも含め、質問の内容についてご意見をいただけましたら幸いです。
horse_n_deer
horse_n_deer

2016/06/13 12:34

「プロセスが終了しない」を再現できる`taskB_Work`の内容を書くことは可能ですか?再現できない以上は、「ファイルの監視やサーバーのlistenなど、中でプロセスが落ちない処理を実行している」という予想くらいしか付かないです。
TEA
TEA

2016/06/14 00:58

`taskB_Work`の内容を追記しました。node-flickrapiを利用しているのですが、そのコールバックでreject();している事が問題なのかなと考えていますが、具体的な事が分かりません。taskB_Workは配列要素の数だけ実行され、最後にtaskCが実行されますが、プロセスが落ちない状況となっています。こちらについてご意見をいただけましたら幸いです。 また、promiseの記述方法については、一つ目で示したjavascriptコードのような記述で問題ないでしょうか?promiseに関する記述が原因でプロセスが落ちない原因となっていないかも不明でしたので、差し支えなければこの件につきましてもご意見をお待ちしております。
TEA
TEA

2016/06/17 00:43

ご返事いただきありがとうございます。npm install bluebirdとvar Promise = require('bluebird');した後で、process.on('unhandledRejection',.. を追加してみましたが、何かのエラーがcatchされる気配はありませんでした。。。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。