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

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

ただいまの
回答率

88.90%

JavaScriptのPromise処理で値が帰ってこない

解決済

回答 2

投稿

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

hososo

score 32

質問を読んで頂きありがとうございます。

ユーザがファイルをアップロードし、それを加工して表示するというプログラムを作ろうとしています。
ファイルをアップロード→内容を加工という処理を同期的に行うためにPromiseを使いましたが、値が上手く帰ってきません。
下記がそのコードです。雰囲気が伝わるよう、なるべく省略しないようにしましたので長くなってしまいましたがお許しください。

// 読み込み1 ユーザがアップロードしたファイル1を加工して返却する。
function getMasterCSV() {
  return new Promise((resolve, reject)=>{
    try {
      let masters = [];
      let fileInput = document.getElementById('openMasterCSV_btn');
      let fileReader = new FileReader();
      fileInput.onchange = () => {
        let file = fileInput.files[0];
        fileReader.readAsText(file);
      };
      fileReader.onload = () => {
        let result = fileReader.result;
        // (略)加工処理をしてmastersに代入
        resolve(masters);
      }
    } catch (e) {
      reject(e);
    };
  });
};

// 読み込み2 ユーザがアップロードしたファイル2を加工して返却する。
function getTransferCSV() {
  return new Promise((resolve, reject)=>{
    try {
      let transfers = [];
      let fileInput = document.getElementById('openTransferCSV_btn');
      let fileReader = new FileReader();
      fileInput.onchange = () => {
        let file = fileInput.files[0];
        fileReader.readAsText(file);
      };
      fileReader.onload = () => {
        let result = fileReader.result;
        // (略)加工処理をしてtransfersに代入
        resolve(transfers);
      }
    } catch (e) {
      reject(e);
    };
  });
};

async function main() {
  // 読み込まれたデータを受け取る
  let masters = await getMasterCSV();
  let transfers = await getTransferCSV();
  console.log(masters);    // なにも表示されない(undefinedとかでもない)
  console.log(transfers);  // なにも表示されない(undefinedとかでもない)
}

main();


このようなコードです。main()console.logではなにもコンソールに表示されなかったので、awaitはちゃんと機能している模様です。しかしresolve()した内容が帰ってきません。getMasterSCV getTransferCSVでエラーがあるのかとも思い、tryを噛ませてみましたがなにも表示されませんでした。

色々調べてみたのですが解決できず質問しました。回答よろしくお願致します。また、このようなファイルを読み込む処理ではそもそもPromiseを利用すべきではない、等の意見でもありがたいです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • raccy

    2020/07/19 07:06

    コードを見る限りmastersやtransfersを返しているように見えますが、
    // (略)加工処理をしてmastersに代入
    の部分で具体的に何をしているのか不明のため、空文字列でも代入しているのかと思ってしまいます。まずは、Promiseの動作の確認のために、
    masters.push("abc");
    とか適当に書いた場合でも値は返ってこないか確認してみてください。

    キャンセル

  • maisumakun

    2020/07/19 08:24

    2つのファイル入力フォームでファイルの選択は行いましたか?

    キャンセル

  • AkitoshiManabe

    2020/07/19 12:06

    ご質問の内容は「ブラウザでは処理できない」という回答も有効です。
    理由:「(アップロード直後の)サーバー側で処理すべき事例」と受け取れるため
    > ユーザがファイルをアップロードし、それを加工して表示する
    > ファイルをアップロード→内容を加工という処理
    ブラウザ側での処理を実装するなら「(アップロード直前の)プレビュー時点で加工処理して表示」であり、「ファイル選択→プレビュー&加工→アップロードという処理」ではないでしょうか?

    キャンセル

  • hososo

    2020/07/19 14:17

    自己解決という形になりましたが、大変助かりました。皆さんありがとうございます!

    >> raccyさん
    「Promiseの動作の確認のために、masters.push("abc");とか適当に書いた場合でも値は返ってこないか確認してみてください。」のアドバイスが大変役に立ちました。デバック部分を分離することにより原因解明がはかどりました。ありがとうございます!

    >> maisumakunさん
    はい。入力フォームで選択を行いました。

    >> AkitoshiManabeさん
    混乱させて申し訳ございません。自己解決の欄に詳しく記述しましたが、提示したコードはフロント側のコードです。

    キャンセル

回答 2

check解決した方法

0

まず最初に、私のあやふやな質問文で提示したコードがフロントの処理なのかサーバーの処理なのかで混乱させてしまったことをお詫びします。私が提示したコードはフロントで、ユーザがブラウザにアップロードした(この場合はアップロードとはいわないのかもしれません)csvファイルを、ブラウザに表示するという内容です。

解決に至った理由ですが、これは提示したコードには含まれていない

let dataRecode = new Vue({
  el: '#dataRecode',
  data: {
    items: {},
  }
})


の部分を削除することで解決しました。いくつかの回答を元に色々と試していくとこれはPromiseの問題ではなくファイルのアップロード処理に問題があるとわかり、そこに焦点を絞っていくと該当のVue.jsのコードを削除すると上手くということがわかりました。理由は不明です。

自己解決という形ですが、この結論に至るまでに回答に助けられた場面も多々ありましたので、お礼申し上げます。ありがとうございました!

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/19 14:29

    ファイルのアップロードでファイルリーダーを使うのはあまり意味がないです
    アップロードせずにサムネイルを作ったりするときにご利用ください
    ファイルをFormDataでfetchするほうが効率的なので、時間ができたら
    よくよく検討してみてください

    キャンセル

  • 2020/07/19 14:48

    知りませんでした。試してみようと思います。アドバイスありがとうござます!

    キャンセル

0

  • myfile.html
<script>
window.addEventListener('DOMContentLoaded',()=>{
  document.querySelector('#myfile').addEventListener('change', async e=>{
    const body=new FormData();
    body.append(e.target.name,e.target.files[0]);
    const method="post";
    const v=await fetch("myfile.php",{body,method}).then(res=>res.text());
    document.querySelector('#view').textContent=v;
  });
});
</script>
<input type="file" name="myfile" id="myfile">
<div id="view"></div>
  • myfile.php
<?PHP
if(isset($_FILES["myfile"])){
  $fp=fopen($_FILES["myfile"]["tmp_name"],"r");
  $content="";
  while(!feof($fp)){
    $content.=fread($fp,10);
  }
  fclose($fp);
  print "start\n".$content."\nend";
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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