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

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

ただいまの
回答率

88.81%

Node.jsでのDBデータ取得を同期処理にしたい

解決済

回答 1

投稿 編集

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

aiai8976

score 73

前提・実現したいこと

Node.jsでwebサーバをつくっています。
そのひとつの処理にDBデータを検索して取得する部分があるのですが、Node.jsは非同期処理なので処理が終わる前に次に進んでしまい、空のまま渡してしまってエラーが起きているという状況です。
そこでその処理が終わったあとに次にすすむよう同期処理にしたいのですが、うまくいきません。
以下のサイトを見ながらPromiseを使おうとしましたが、同期処理できない状況です。
https://blog.honjala.net/entry/2018/08/08/022027
何か解決策があればコメントお願いします。

発生している問題・エラーメッセージ

$ node webServer.js
Server running 
Connected correctly to server
/
/js/three.js-master/build/three.min.js
/js/OrbitControls.js
/css/index.css
/get_value
レスポンス
undefined
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer. Received type undefined
    at write_ (_http_outgoing.js:595:11)
    at ServerResponse.write (_http_outgoing.js:567:10)
    at Object.getValue (/home/hasegawa/デスクトップ/akiyama/Node.js/webServer.js:137:17)
    at process._tickCallback (internal/process/next_tick.js:68:7)
/favicon.ico
はいった

該当のソースコード

//DB接続準備
const MongoClient = require('mongodb').MongoClient;
const url_db = 'mongodb://localhost:27017'; // Connection URL
const dbName = 'study'; // Database Name
const client = new MongoClient(url_db, { useNewUrlParser: true });
const assert = require('assert');
var collection;
//var value;



// Use connect method to connect to the server
client.connect(function (err) {
    assert.equal(null, err);
    console.log("Connected correctly to server");

    const db = client.db(dbName);

    // Get the documents collection
    collection = db.collection('user');

    /*collection.find({}).sort({ time: -1 }).toArray(function (err, docs) {
        console.log("はいった");
        for (var doc of docs) {
            value = doc;
            break;
        }
        //value = docs;
    });*/
});

function asyncFunc() {
    return new Promise((resolve) => {
        // ...何かしらの時間がかかる処理...
        let result;

        collection.find({}).sort({ time: -1 }).toArray(function (err, docs) {
            console.log("はいった");
            for (let doc of docs) {
                result = doc;
                break;
            }
            //value = docs;
        });

        process.on('unhandledRejection', console.dir)
        resolve(result);
    });

}


// http.createServerがrequestされたら、(イベントハンドラ)
server.on('request', function (req, res) {
    // Responseオブジェクトを作成し、その中に必要な処理を書いていき、条件によって対応させる
    var Response = {
        "renderHTML": function () {

        },
        "getThree": function () {

        },
        "getOrbit": function () {

        },
        "getCSS": function () {

        },
        "getValue": async function () {

            let value = await asyncFunc();
            //client.close();

            // HTTPレスポンスヘッダを出力する
            res.writeHead(200, {
                'content-Type': 'text/html',
                'Access-Control-Allow-Origin': '*'
            });

            console.log("レスポンス");
            //console.log(result);

            console.log(value);
            // HTTPレスポンスボディを出力する
            res.write(JSON.stringify(value));
            res.end();
        },
        "postData": function () {

    };
    // urlのpathをuriに代入
    var uri = url.parse(req.url).pathname;
    console.log(uri);


    // URIで行う処理を分岐させる
    if (uri === "/") {
        // URLが「IPアドレス/:1234/」の場合、"renderHTML"の処理を行う
        Response["renderHTML"]();
        return;
    } else if (uri === "/js/three.js-master/build/three.min.js") {
        // URLが「IPアドレス/:1234/js/three.js-master/build/three.min.js」の場合、"getThree"の処理を行う
        Response["getThree"]();
        return;
    } else if (uri === "/js/OrbitControls.js") {
        // URLが「IPアドレス/:1234/js/OrbitControls.js」の場合、"getOrbit"の処理を行う
        Response["getOrbit"]();
        return;
    } else if (uri === "/css/index.css") {
        Response["getCSS"]();
        return;
    } else if (uri === "/get_value") {
        // URLが「IPアドレス/:1234/get_value」の場合、"getThree"の処理を行う
        Response["getValue"]();
        return;
    } else if (uri === "/post_data") {
        // URLが「IPアドレス/:1234/post_data」の場合、"postData"の処理を行う
        Response["postData"]();
    };
});

// 指定されたポート(1234)でコネクションの受け入れを開始する
server.listen(1234);
console.log('Server running ');
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

ノーチェックなので予想でしか無いですがソースコメントで記載しておきます

        collection.find({}).sort({ time: -1 }).toArray(function (err, docs) {
            console.log("はいった");
            for (let doc of docs) {
                result = doc;
                break;
            }
            //value = docs;
            // ここでresolveするべきでは
        });

        process.on('unhandledRejection', console.dir)
        resolve(result); // <-ここでresolveしてるけど、collection.findが非同期でしょうからresultは空では?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/06 11:47

    ありがとうございます!いけました!
    collection.findも非同期なので空のままresolveを返してしまっていたということですね。
    勉強になりました。

    キャンセル

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

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

関連した質問

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