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

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

ただいまの
回答率

90.37%

  • JavaScript

    21597questions

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

  • Node.js

    2476questions

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

  • Firebase

    1026questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

  • Chrome extension

    152questions

    Chrome拡張機能

  • 非同期処理

    145questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

async/awaitでasync functionのfunctionに対してunexpected tokenのエラーがでる

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,056

TarouKotani

score 34

firebaseを利用したサーバサイドの開発をしており、非同期処理を同期的に直す過程でエラーが出ました。

データをajaxで受け取る→それをfirebaseのデータベースと突合→合致する場合はresponse(500)を帰す
というバックエンドの処理をしようとしています。

「データを格納→完了後に突合」としたく、async/awaitの非同期処理の最後の例にならって、
promise,async,awaitを用いた非同期処理の待ちを実装しましたが、下記のエラーが出ます。

65:9  error  Parsing error: Unexpected token function

/////////////////////////////////////////index.js//////////////////////////////////

const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
// The Firebase Admin SDK to access the Firebase Realtime Database.

// Import Admin SDK
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

// Get a database reference to our posts
var db = admin.database();
var ref  = db.ref("/product");

//chromeExtensionからのデータを受信
exports.product = functions.https.onRequest((request, response) => {
    //POSTを受けると発火
    if (request.method === "POST") {
        const body = request.body;
        const pushRef = admin.database().ref("/product").push();
        pushRef.set({
          //薬処方時のデータ
          patientId: body["patientId"],
          doctor:    body["doctor"],
          idisease:  body["idisease"],
          medicine:  body["medicine"],
          medicineID:body["medicineID"],
        }, error => {
            if (error) {
                console.log("save error", error.message);
            } else {
                console.log("save Success!!");
            }
        }
      );
  }//ajaxの受け取り

////////////////////////////////////////////////////////////////////  問題個所はここ以降
  //medicineIDを薬マスタと突合

  //薬のIDを配列に格納
  function getInMedId() {
    const p = new Promise((resolve,reject) => {
      var inMedId = body.medicineID;
      resolve(inMedId);
    });
    return p;
  }

  //マスター側の薬のIDを配列に格納
  function getPreMedId() {
    const q = new Promise((resolve,reject) => {
       var preMedId = [];
       for(j=0; j<(90+1); j++){
         var m = db.ref("/"+j+"/medicineId");
         m.on("value", function(snapshot){
           preMedId = snapshot.val();
         });
       }
       resolve(preMedId);
     });
     return q;
   }

  //薬のIDを突合
  async function checkMedId() {         <============================================ ※エラー箇所※
   for(i=0; i<inMedId.length+1; i++){
     for(j=0; j<(90+1); j++){
       var a = await getInMedId();
       var b = await getPreMedId();
       if(a[0][i] === b[j]){
         console.log('This medicine is skeptical:'+a);
         response.status(500).send(error.message).end();
       }
     }
   }
 }
 checkMedId();
  //for回して無事だったら普通のレスポンス
 response.status(200).end();

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+7

というか、そもそも構文エラーで質問する以前の問題です。
インデントもぐちゃぐちゃなのでまずはESLint等を導入してエラーを取り除いてください。
正しく括弧や波括弧の整合性があってるのか確認してください。

もしコードが正しければNode.jsのバージョンが古い可能性があります。
http://node.green/#ES2017-features-async-functions

async / awaitはバージョン7.10以降に実装された書き方ですので、
下記のコマンドでNode.jsのバージョンを確認し、古ければ新しいバージョンをインストールしてください。
基本的にECMAScriptは下位互換を強く意識しているので、酷いバグでも無い限り出来るだけ最新を入れたほうが良いです。

$ node -v

さて、コードが動くようになれば恐らく次の問題が出てくるでしょう。
なので先受けして書いておきます。
(今回のエラーはあくまで構文エラーなので、asyncがどうのとかそういう以前の問題です)

async function () {}を同期処理と勘違いしていませんか?
この形式で書かれた場合、必ずPromiseが戻り値になります。

もしreturn 123;というに正常終了していれば、resolve(123)が実行された事になります。
throw new Error('エラー理由')という風に例外を投げれば、reject(new Error('エラー理由'))が実行された事になります。

つまり、構文の上で取り繕うだけで、
いくら取り繕ったとしても非同期は非同期であり、単なるPromiseです。


これを元にコードを見ていきましょう。

  //薬のIDを突合
  async function checkMedId() {
   for(i=0; i<inMedId.length+1; i++){
     for(j=0; j<(90+1); j++){
       var a = await getInMedId();
       var b = await getPreMedId();
       if(a[0][i] === b[j]){
         console.log('This medicine is skeptical:'+a);
         response.status(500).send(error.message).end();
       }
     }
   }
 }
 checkMedId();
  //for回して無事だったら普通のレスポンス
 response.status(200).end();

まずcheckMedId()が実行されます。
中身はPromiseな上二重ループの中で何度もawait getInMedId()等が呼ばれているので、
非同期でありその場での処理を諦めています。

なのでどうあがこうが先にresponse.status(200).end();が叩かれ、ステータスコード200が確約されます。
その後、checkMedId内の変数aとbが確定され、response.status(500).send(error.message).end();を実行しようとします。
それ以前にerrorが宣言されてませんが

これはExpressですか?
Expressはステータスコードを二重に宣言しようとしたり、.end後になにかを返そうとすればエラーになります。
こういった流れでエラーが発生しているようです。

ではどうすればよかったのか。
Promiseを叩いて受けるようにコードを修正しましょう。

  // 薬のIDを突合
  async function checkMedId() {
    for(i=0; i<inMedId.length+1; i++){
      for(j=0; j<(90+1); j++){
        var a = await getInMedId();
        var b = await getPreMedId();
        if(a[0][i] === b[j]){
          throw new Error('This medicine is skeptical:' + a)
        }
      }
    }
  }
  // 普通のPromiseだと思って対応する
  checkMedId()
    .then(() => {
      response.status(200).end();
    })
    .catch(err => {
      console.log(err.message);
      response.status(500).send(err.message).end();
    })

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/08 16:07

    もろもろありがとうございます。。。
    バージョンを確認し、最後の通りに直しましたがやはり同じエラーが出ます。。

    キャンセル

  • 2018/03/08 16:36

    質問文を私のローカルで構文解析したところエラーは出ませんでした。
    従って転記ミスの可能性が高いです。

    またさらっとですがコードを一通り読みました。
    ・getPreMedIdの中身が明らかにおかしいです。
     DBに接続してpreMedIdよこせって言ってるのに、待たずに即返してるので絶対にUndefindが帰ります。
    ・for文で90回もループしてますが、これ本当に合ってますか?
     90回もループしつつその中で90回また固定値でループし始めるプログラムってかなりおかしいですよ。

    キャンセル

+2

firebaseと言ってもたくさんのプロダクトがありますが、コードを拝見するにFirebase Cloud Functionsのこととお見受けします。

で、現時点(2018.05.15)におけるFirebase Cloud FunctionsのNode環境はv.6.11.5となります。

ローカルがv7.10以降でも、firebaseクラウド環境がNode v.6.11.5ですのでasync/awaitは一工夫しないと使えません。そのためasyncキーワードでunexpected tokenエラーが発生したものと思われます。


それと、少々耳の痛い話かもしれませんが、仮にasync/awaitが使えたとしてもコードの内容に突っ込みどころが多く想定している動作をしないように思います。

面倒かもしれませんが要素技術ごとに分解して簡略化した最小コードを書いてみることをお勧めします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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

  • JavaScript

    21597questions

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

  • Node.js

    2476questions

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

  • Firebase

    1026questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

  • Chrome extension

    152questions

    Chrome拡張機能

  • 非同期処理

    145questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。