この間使ってみたNeDB、
とても便利なんですが、各種APIがcallback形式のものとなっていて、、安易にコールバック地獄に突入してしまいそうな雰囲気を感じます。
NeDBを使ってNode.js環境でお手軽にNoSQLのDBを使ってみる - SourceChord
せっかくTypeScriptで書くなら、やっぱasync/awaitと一緒に書きたい!!
ということで、asyncな呼び出しができるようなラッパークラスを書いてみました。
コード一式は、以下の場所に上げておきました。 github.com
こんな風に、awaitしながら呼び出すことができます。
async function main() { await db.loadDatabaseAsync(); // 初期データの書き込み await db.insertAsync(doc); // 全件表示var allItems = await db.findAsync({}); console.log("■全件表示"); console.dir(allItems); // findでの検索var searchResult1 = await db.findAsync({ name: "hoge2"}); console.log("■findでの検索"); console.dir(searchResult1); }
やっぱこうやってawaitで待機できると、ちょっと入り組んだ処理になっても、とても理解しやすいですね。
こんな風にPromiseでラップした関数呼び出しを追加したクラスを作り、このクラスを通してasyncな関数を呼ぶようにしています。
import * as NeDBDataStore from "NeDB"; exportclass AsyncNeDBDataStore extends NeDBDataStore {/** * コンストラクタ1 */ constructor(); constructor(path: string); constructor(options: any); constructor(args?: any) {super(args); }// 後で、戻り値を考え直すpublic loadDatabaseAsync(): Promise<void> {returnnew Promise((resolve, reject) => super.loadDatabase((err) => {if (err) { reject(err); }else{ resolve(); }})); }public ensureIndexAsync(options: Object): Promise<void> {returnnew Promise((resolve, reject) => super.ensureIndex(<any>options, (err) => {if (err) { reject(err); }else{ resolve(); }})); }public removeIndexAsync(fieldName: string): Promise<void> {returnnew Promise((resolve, reject) => super.removeIndex(fieldName, (err) => {if (err) { reject(err); }else{ resolve(); }})); }public insertAsync<T>(newDoc: T): Promise<T> {returnnew Promise((resolve, reject) => super.insert(newDoc, (err, document) => {if (err) { reject(err); }else{ resolve(document); }})); }public countAsync(query: any): Promise<number> {returnnew Promise((resolve, reject) => super.count(query, (err, n) => {if (err) { reject(err); }else{ resolve(n); }})); }public findAsync<T>(query: any): Promise<Array<T>>; public findAsync<T>(query: any, projection: T): Promise<Array<T>>; public findAsync<T>(query: any, projection?: T): Promise<Array<T>> {if (projection) {returnnew Promise((resolve, reject) => super.find(query, projection, (err, documents) => {if (err) { reject(err); }else{ resolve(documents); }})); }else{returnnew Promise((resolve, reject) => super.find(query, (err, documents) => {if (err) { reject(err); }else{ resolve(documents); }})); }}public findOneAsync<T>(query: any): Promise<T>; public findOneAsync<T>(query: any, projection: T): Promise<T>; public findOneAsync<T>(query: any, projection?: T): Promise<T> {if (projection) {returnnew Promise((resolve, reject) => super.findOne(query, projection, (err, document) => {if (err) { reject(err); }else{ resolve(document); }})); }else{returnnew Promise((resolve, reject) => super.findOne(query, (err, document) => {if (err) { reject(err); }else{ resolve(document); }})); }}public updateAsync<T>(query: any, updateQuery: any, options: any): Promise<{ numberOfUpdated: number, affectedDocuments: any, upsert: boolean}> {returnnew Promise((resolve, reject) => super.update(query, updateQuery, options, (err, numberOfUpdated, affectedDocuments, upsert) => {if (err) { reject(err); }else{ resolve({ numberOfUpdated, affectedDocuments, upsert }); }})); }public removeAsync<T>(query: any): Promise<number>; public removeAsync<T>(query: any, options: any): Promise<number>; public removeAsync<T>(query: any, options?: any): Promise<number> {if (options) {returnnew Promise((resolve, reject) => super.remove(query, options, (err, n) => {if (err) { reject(err); }else{ resolve(n); }})); }else{returnnew Promise((resolve, reject) => super.remove(query, (err, n) => {if (err) { reject(err); }else{ resolve(n); }})); }}}