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

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

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

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

JavaScript

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

Q&A

解決済

3回答

268閲覧

JavascriptのPromiseについて

kazzzstudio

総合スコア94

Node.js

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

JavaScript

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

0グッド

1クリップ

投稿2018/03/24 07:12

Javascript(Nodejs)とcheerio-httpcliを使ってスクレイピングの処理を書いているのですが、実行順序がコントロールできずに途中でプログラムが終わってしまいます。

Javacsript

1var loopProcess = function(callback) { 2 return new Promise(function(resolve, reject) { 3 for (i = 0; i < _keyword_array.length; i++) { 4 console.log("Inside Loop") 5 // 指定された検索エンジンによって処理を分ける 6 if (_search_engine == "google") { 7 goGoogle(_keyword_array[i], _user_agent, _check_keyword) 8 } 9 else { 10 goYahoo(_keyword_array[i], _user_agent, _check_keyword) 11 } 12 } 13 }) 14} 15 16// 結果を出力する 17var finishProcess = function() { 18 return new Promise(function(resolve, reject) { 19 _result_html += "</table>" 20 _result_area.innerHTML += _result_html 21 console.log("finish end process") 22 }) 23} 24 25loopProcess().then(finishProcess())

_keyword_arrayには3件のテストデータが入っており、for文は3回回らなければなりません。
しかし、
Inside Loopのログが1回だけ出て、その後は、finish end processと出て終わってしまいます。
何か書き方が悪いことはわかるのですが、どこをどう直せばいいのかがわかりません。

よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

何か書き方が悪いことはわかるのですが、どこをどう直せばいいのかがわかりません。

コードを見る限りPromiseについて分かっていないで書いているようなので、
まずはPromiseについてまずは学ぶと良いのではないでしょうか。
そして、その後、必要であれば質問を再度されていはいかがですか?

投稿2018/03/24 07:32

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazzzstudio

2018/03/27 05:22

まさにおっしゃる通りであることはわかっていたのですが、納期が迫っていたため止むを得ずお聞きしたという次第です。なんとか動くコードが作れたのでよかったです。これから勉強します。
guest

0

ベストアンサー

各変数の中身が分からないので、
回答者が最後まで面倒みるのは不可能です。

Promiseの書き方は試行錯誤の後が見れますが、sousukeさんの仰るように
何か簡単なresolveやrejectを発火するコードを書いて動作を確かめてみてください。

さて、それ以外のどう見ても駄目そうな箇所を幾つか突っ込みます。

  • var loopProcess = function(callback)このコールバック関数は何?
  • goGoogleとgoYahooって非同期な処理じゃないの?
  • .then(finishProcess())何も待たずに発火して評価開始してる件

var loopProcess = function(callback)このコールバック関数は何?

試行錯誤の後でしょうね。
これは普通の非同期処理を書く時のやり方で、
新しいPromiseを使った非同期処理の時は不要です。

コードを見せる時に削っておきます。

goGoogleとgoYahooって非同期な処理じゃないの?

質問文に「Inside Loopのログが1回だけ出て」という記載があるのでほぼ確定でしょう。
goGoogleがコールバック関数を要求するのか、はたまたPromiseを返すのかでまた分岐しますが、
全て実行完了するのを待ってからresolve(value)にするべきでしょう。

もっと言うなら、お外のスコープで宣言した_result_htmlを書き換える設計は死ぬほどダサいです。
resolve(value)の中身を_result_htmlとして実行するべきでしょう。

更に一手進めてasync / awaitを使ってリファクタリングすればこんな感じになると想定されます。

JavaScript

1// loopProcess :: Object -> Promise 2const loopProcess = async options => { 3 const {search, keywords, user_agent, check_keyword} = options 4 const results = [] 5 for (const keyword of keywords) { 6 console.log("Inside Loop") 7 // なんでキーワード全て同じ検索エンジンになるの?外からもってきなさい 8 // searchはPromiseを返す関数と決め打ちしてawaitで待つ 9 const result = await search(keyword, user_agent, check_keyword) 10 results.push(result) 11 } 12 return results 13} 14 15// 恐らくgoGoogleとgoYahooもリファクタリングの必要あり 16const search = _search_engine == "google" ? goGoogle : goYahoo 17const options = { 18 search, 19 keywords: _keyword_array, 20 user_agent: _user_agent, 21 check_keyword: _check_keyword 22} 23loopProcess(options)

.then(finishProcess())何も待たずに発火して評価開始してる件

発火させてはいけません。
前のPromiseのresolve(value)の第一引数(value)がthenの第一引数に格納されて発火される作りになっているからです。

このように記述してください。

JavaScript

1// Promiseである必要はないので普通の関数にした 2finishProcess = (html, area, results) => { 3 // TODO: resultsを加工する 4 const result_html = toResultHTML(results) 5 area.innerHTML += html + result_html + "</table>" 6 console.log("finish end process") 7} 8 9// options変数は前章を参考 10// _result_htmlと_result_areaはfn.prototype.bindを使って束縛する 11loopProcess(options) 12 .then(finishProcess.bind(null, _result_html, _result_area))

投稿2018/03/24 15:15

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazzzstudio

2018/03/27 05:20

わかりやすいご説明ありがとうございます!
guest

0

resolve()とreject()してないですね…。
promiseは簡単にいうと
・resolveしたときにthenコールバックに入る
・rejectしたときにcatchコールバックに入る
というものですよ。

両方とも呼んでないので意味をなさないコードになっています。
使い方を調べた方がよろしいかと。

投稿2018/03/24 09:06

sousuke

総合スコア3828

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazzzstudio

2018/03/27 05:21

勉強が足りませんでした。もっとよく調べます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問