Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@Fushihara

nodejsのsqlite3モジュールをPromiseの非同期処理で使う

nodejsのsqliteモジュールで一番DL数が多いsqlite3。
https://www.npmjs.com/package/sqlite3
https://github.com/mapbox/node-sqlite3

コールバックはもう使いたくないのでPromise対応にした。コールバックにPromise.resolve()を付けてるだけだけど。

npmにある他のsqliteモジュールはDL数が桁違いで少なくて使うのが怖いので自作。

メモ

  • 既存のsqlite3モジュールはコールバックの他に、runで独自のthisをbindしているのでアロー関数が使えない。
  • foreachは途中でキャンセルが出来なくて無意味との事なのでスルー。allでやる。
  • その結果、run、get、all、prepareで十分 のはず。serializeやparallelizeは正直良くわからん
sqlite3.js
const sqlite = require('sqlite3').verbose();
class sqlite3{
  constructor(dbFileName){
    // https://github.com/mapbox/node-sqlite3/wiki/API
    this.db = new sqlite.Database(dbFileName);
  }
  /// 戻り値は数字。updateとかdelete分に使う
  run(query,param){
    const p = new Promise((ok,ng)=>{
      this.db.run(query,param,function(err,res){
        // bindしてthisを書き換えてるのでアロー関数は出来ない
        let lastId  = this.lastID  || -1;
        let changes = this.changes || -1;
        if(err){
          ng(new Error(err));
        }else{
          ok({lastId:lastId,changes:changes});
        };
      });
    });
    return p;
  }
  /// 1アイテムだけselectする。結果が0件の時はundefinedになる
  get(query,param){
    const p = new Promise((ok,ng)=>{
      this.db.get(query,param,(err,res)=>{
        if(err){
          ng(new Error(err));
        }else{
          ok(res);
        };
      })
    });
    return p;
  }
  /// 全てselectする
  all(query,param){
    const p = new Promise((ok,ng)=>{
      this.db.all(query,param,(err,res)=>{
        if(err){
          ng(new Error(err));
        }else{
          ok(res);
        };
      })
    });
    return p;
  }
  prepare(query){
    // ここのパラメーターが有効になる条件がわからなかったので、prepareの引数はクエリ文字だけで
    let r = this.db.prepare(query,{});
    return new sqlite3_prepare(r);
  }
}
// finalizeやresetの使い方がわからなかったのでrunだけ
class sqlite3_prepare{
  constructor(statement){
    this.statement = statement;
  }
  run(query){
    const p = new Promise((ok,ng)=>{
      this.statement.run(query,()=>{ok()});
    });
    return p;
  }
}
module.exports = sqlite3;

使い方はこんな感じ

index.js
const sqlite3    = require('./sqlite3');
async function main(){
  const db = new sqlite3("./database.db");
  let yyyList = await transactionText(db);
}
main();
function transactionText(db){
  return Promise.resolve()
    .then(()=>{
      return db.run("BEGIN");
    }).then(()=>db.run(`insert into xxx (v)values(?)`,["test"]))
      .then((item)=>{
        let insertId = item.lastId;
        let statement = db.prepare("INSERT INTO yyy (sub_id,val) VALUES (?,?)");
        return Promise.all(["a","b","c"].map((id)=>{
          return statement.run([insertId,id]);
        }));
    }).then(()=>db.run("COMMIT"))
    }).then(()=>db.get(`select * from yyy`));
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?