Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした