BETA

後編-JS初心者がMongodbデータベースを使って、じっくり非同期処理(callback, async)を勉強し直してみた

投稿日:2018-11-29
最終更新:2018-11-29

async編

  • 前回の記事の続きです。

  • 今回は既に、insert処理を2つ用意してあります。

  • appAsync.js

const MongoClient = require('mongodb').MongoClient
const assert = require('assert')

const url = 'mongodb://localhost:27017'
const dbName = 'myproject'

const client = new MongoClient(url)

const main = async () => {
    try {
        await client.connect()
        console.info("Connected correctly to Server")
        const db = client.db(dbName)
        const collection = db.collection('documents')
        let r = null

        r = await collection.insertOne({ a: 1 })
        assert.equal(1, r.insertedCount)
        console.log('insertOne: ', r.result)

        r = await collection.insertMany([
            { a: 2 },
            { a: 3 },
        ])
        assert.equal(2, r.insertedCount)
        console.log('insertMany: ', r.result)

        client.close()

    } catch (err) {
        console.error(err.stack)
    }
}

main()
  • 実行してみます。
node appAsync.js

Connected correctly to Server
insertOne:  { n: 1, ok: 1 }
insertMany:  { ok: 1, n: 2 }
  • 結果ログが流れているので、正常に挿入が出来ているはずです。
  • 結果表示できるようにもしたいと思います。
const MongoClient = require('mongodb').MongoClient
const assert = require('assert')

const url = 'mongodb://localhost:27017'
const dbName = 'myproject'

const client = new MongoClient(url)

const main = async () => {
    try {
        await client.connect()
        console.info("Connected correctly to Server")
        const db = client.db(dbName)
        const collection = db.collection('documents')
        let r = null

        r = await collection.insertOne({ a: 1 })
        assert.equal(1, r.insertedCount)
        console.log('insertOne: ', r.result)

        r = await collection.insertMany([
            { a: 2 },
            { a: 3 },
            { a: 4 },
            { a: 5 },
            { a: 6 },
        ])
        assert.equal(5, r.insertedCount)
        console.log('insertMany: ', r.result)

        r = await collection.find().toArray()
        console.log(r)

        client.close()

    } catch (err) {
        console.error(err.stack)
    }
}

main()
  • client.close()を最後にかけば、ちゃんと最後に処理してくれるのが、asyncの良いところです。

  • データがこのままだと、実行毎に際限なく増えるので、一旦データを削除処理してから、insertをしたいと思います。 順番に処理されるのですから、最初にかければいいですね。


const MongoClient = require('mongodb').MongoClient
const assert = require('assert')

const url = 'mongodb://localhost:27017'
const dbName = 'myproject'

const client = new MongoClient(url)

const main = async () => {
    try {
        await client.connect()
        console.info("Connected correctly to Server")
        const db = client.db(dbName)
        const collection = db.collection('documents')
        let r = null

        r = await collection.deleteMany()
        console.log('deleteMany: ', r.result)

        r = await collection.insertOne({ a: 1 })
        assert.equal(1, r.insertedCount)
        console.log('insertOne: ', r.result)

        r = await collection.insertMany([
            { a: 2 },
            { a: 3 },
            { a: 4 },
            { a: 5 },
            { a: 6 },
        ])
        assert.equal(5, r.insertedCount)
        console.log('insertMany: ', r.result)

        r = await collection.find().toArray()
        console.log(r)

        client.close()

    } catch (err) {
        console.error(err.stack)
    }
}

main()
  • これで、データの数は固定化されました。 これは あくまでもテストデータなので消したり挿入を繰り返しています、実際はこんな実装しないと思います。

  • main の処理系のコードが増えてきたので、こちらも別関数に変更していきたいと思います。


const MongoClient = require('mongodb').MongoClient
const assert = require('assert')

const url = 'mongodb://localhost:27017'
const dbName = 'myproject'

const client = new MongoClient(url)

const findDocuments2 = (db) => {
    const collection = db.collection('documents')
    return collection
        .find({})
        .project({ '_id': 0})
        .toArray()
}

const findDocuments1 = (db, callback) => {
    const collection = db.collection('documents')
    collection
        .find({})
        .project({ '_id': 0})
        .toArray((err, docs) => {
            assert.equal(err, null)
            console.log("Found the records callback")
            callback(docs)
        })
}

const insertManyDocuments = (db) => {
    const collection = db.collection('documents')
    collection.insertMany([
            { a: 2 },
            { a: 3 },
            { a: 4 },
            { a: 5 },
            { a: 6 },
        ])
        .then(result => console.log('insertMany: ', result.result))
        .catch(err => console.error(err))
}

const insertOneDocument = (db) => {
    const collection = db.collection('documents')
    return collection.insertOne({ a: 1})
}

const deleteManyDocuments = (db) => {
    const collection = db.collection('documents')
    collection.deleteMany()
        .then(result => console.log('deleteMany: ', result.result))
        .catch(err => console.error(err))

}

const main = async () => {
    try {
        await client.connect()
        console.info("Connected correctly to Server")
        const db = client.db(dbName)
        // const collection = db.collection('documents')
        let r = null

        await deleteManyDocuments(db)

        r = await 2 + 3 // await処理は必要ないがあっても、エラーにならない
        console.log(r)

        r = await insertOneDocument(db)
        console.log('insertOne: ', r.result)

        await insertManyDocuments(db)

        await findDocuments1(db, result => {
            console.log(result)
        })

        r = await findDocuments2(db)
        console.log('Finds: ', r)

        client.close()

    } catch (err) {
        console.error(err.stack)
    }
}

main()
  • asyncの方は、いろんな返し方が出来るので、実装方法で見やすさがだいぶ左右されそうです。
  • async処理で注意する点は、コストが掛かると思われる処理は、すべて await を掛ける必要があるということです。 忘れるとエラーにならなくても意図しない結果になりバグに気づくのに遅れる原因になります。
  • await が必要ない処理に、結果的に掛けてしまっても問題になることは少ないのでかけ忘れるよりかは遥かにマシだと思います。(コストは余計にかかるように思うが未検証)

  • これを読んでくれた方は、わかりやすいかどうかは置いておくとしてコールバックとasyncの違いが把握していただけたのではないかと思います。 そして副次的にデータベースの基本的な操作も出来るようになったと思います。(笑)

  • あと間違っている点をコメントにでも、指摘していただけたら幸いです。m(__)m

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@atoris1192の技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!