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

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

ただいまの
回答率

90.00%

node.js : エラーがどこにあるのかわからない

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 539

Statham

score 75

Fireabaseのcloud functionsで、node.jsを実行しています。

コードはいかの通りです。

const fs = require('fs');
const firebase = require('./firebase');
const storage = firebase.storage;

const createArticleHtml = (snap, context) => {
  console.log("in createArticle Html");
  console.log("snap is this : ", snap);
  const data = snap;
  const md_data_path = data.body;
  console.log("path is : ", md_data_path);
  getMdFileFromStorage(md_data_path)
    .then((md_data) => {
      return mdToHtml(md_data)
    }) // ここから処理が続く
const getMdFileFromStorage = (path) => {
  return new Promise((resolve, reject) => {
    console.log("in getMdFileFromStorage");
    const file = storage.bucket().file(path);
    file.createReadStream()
      .on('error', (err) => {
        console.log("Error in getMdFileFromStorage");
        reject(err);
      })
      .on('response', (response) => {
        console.log("response : ", response);
        console.log("response.read() : ", response.read());
        resolve(response);
      })
      .on('end', () => {
        console.log("getMdFile is finished")
      })
  })
}

以上を実行すると、処理が途中で詰まってしまいます。

FIreabse のコンソール上から確認すると、なぜか、console.logもエラーの記載もなく、処理が止まっていることが確認できます。

具体的には、console.log("in getMdFileFromStorage");が実行されるのを最後に、その先の処理がまったく続きません。
自分の想定としては、file.createReadStream()から先で、エラーなど際にも対応する処理を行っているため、エラーが起きた場合はそのことが何かしらわかるものと考えているのですが、何も表示されません。

なぜ処理が詰まっているのか、お分かりになる方いらっしゃいましたら、お力を貸してほしいです。

よろしくお願いいたします。

参考: cloud storageファイルのcreateReadStream

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

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

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

そもそも何がしたいからgetMdFileFromStorageという関数を用意したのかよくわかりませんが、
createReadStreamはNode.jsのStreamという概念を利用するReadableStreamのインスタンスです。

Node.jsが用意しているStreamというのはその名の通り、川の流れという意味ですから、
exampleにあるように、最後にpipeメソッドを呼び出して別Streamに接続して運河を作らなければいけません。
そうすることで少しずつpipeで繋いだ別のStreamにデータが流れて行きます。
従ってnew Promise(fn)でStreamを包んでも役には立ちません。


しかし、このNode.jsのStreamはかなり難解な実装であり、
省メモリで高速なファイル操作を実現したいみたいな要望で仕方なく使うといった感じのもので、FirebaseがStreamしか用意していないとは思えません。

ではどうすればよかったか?
getMdFileFromStorageとあるように、Strageから何かのファイルを受け取りたかった…つまりダウンロードしたかったんじゃないでしょうか?
もしそうであればcreateReadStreamではなく、downloadメソッドを使うようにすれば解決すると思います。

downloadメソッドは質問者さんの意図通りPromiseのインスタンスを返すようですので少しの手直しで先に進めるんじゃないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/21 11:09 編集

    そうか!
    > Streamというのはその名の通り、川の流れ
    > 別Streamに接続して運河を作らなければいけません

    質問をさせていただく前に、Stream APIについてはいろいろ調べており、データが細切れに読み込まれていくということはわかったのですが、それをどのような場合に使えばいいのかの認識がなかったです。
    「 別Streamに接続して運河を作る」という例えが、大変役立ちました。writableStreamなどに繋げるために利用されると理解しました。

    また、downloadメソッドですが、これも質問する前に試していたのですが、返ってくる内容が、`<Buffer 23 20 ...>`のようなものであったため、何かデータを読み込み中と勘違いし、これでは処理できないものと早とちりしてしまい、Stream に固執していました。

    しかし、これは Buffer クラスのデータであり、中にはしっかりとデータが入っているということに気が付きました。それを`.toString`することで、データを文字列として取り出すことができ、次の処理に繋げることができました。
    参考:
    https://mag.osdn.jp/13/04/09/193000
    http://info-i.net/buffer-string#i-2

    大変丁寧にご回答いただき、大変助かりました。
    おかげ様で、いろいろと理解が深まりました。
    ありがとうございました!

    キャンセル

  • 2018/08/21 12:13

    > それを`.toString`することで、データを文字列として取り出すことができ
    b
    よいNode.jsライフを

    キャンセル

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

  • ただいまの回答率 90.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる