简体   繁体   中英

How to make this global variable hold its value between calls?

I'm trying to reduce the amount of times the database object is initialized in my data access file (variable database inside the file tree-rxdb.mjs ). I created a global variable to hold a reference to the database object and check if it has been initialized before, if it has I just return the variable to the caller without initializing it again. For some reason, the database it's always undefined every time I call this function, even after I have successfully written to the database using the same code. Weirdly, the same doesn't happen to the dao variable inside tree.mjs even though I believe I'm giving it the same treatment but obviously getting differing results. I'm just emulating this code but for some reason it's not working out for the database variable inside tree-rxdb.mjs , what am I not seeing?

tree-rxdb.mjs

import RxDB from 'rxdb';
import adapter from 'pouchdb-adapter-leveldb'
import leveldown from 'leveldown'
import Log from '../utils/log.mjs';
const TAG = 'fruits-rxdb'

RxDB.plugin(adapter)

var database;

const treeSchema = {
    title: 'fruits schema',
    description: 'Describes a fruits tree',
    version: 0,
    type: 'object',
    properties: {
        name: { type: 'string' },
        desc: { type: 'string' },
        url: { type: 'string' },
        state: { 
            type: 'integer',
            enum: [0, 1]
        },
        favorite: {
            type: 'boolean'
        },
        dateAdded: { type: 'string' },
        userId: { type: 'string' }
    }
}

async function connectDB() {
    Log.debug(`Database object = ${database}`, TAG)
    if (database) return database;
    database = await RxDB.create({
        name: 'fruitsdb',
        adapter: leveldown,
        password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
    });
    await database.collection({
        name: 'trees',
        schema: treeSchema
    });
    Log.debug('Database has been initialized', TAG)
    return database;
}

export async function create(tree) {
    const db = await connectDB();
    db.trees.insert(tree.JSON);
}

tree.mjs

import util from 'util'
import logger from '../utils/log.mjs'
import Fruit from './Fruit.mjs'
const TAG = "tree-dao"

var dao;

async function model() {
    logger.debug(`DAO object = ${util.inspect(dao)}`, TAG)
    if(dao) return dao;
    dao = await import(`../dao/tree-${process.env.MODEL}`);
    logger.debug(`DAO model has been initialized: ${util.inspect(dao)}`, TAG);
    return dao;
}

export async function add(){
    const Fruit = new Fruit(undefined, 'Peach', 'peach 123',
        'http://something.com', 0, false, new Date().toISOString(), 'admin');
    (await model()).create(Fruit);
}

app.mjs

import express from 'express';
import logger from 'morgan'; 
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';
import { default as fruits } from "./routes/fruits"
import * as tree from './models/tree.mjs'

const app = express();

app.use(logger("dev"));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use("/fruits", fruits);

const add = async () => {
    await tree.add();
    await tree.add();
    await tree.add();
};
add();

export default app

The problem is that database is only written when the promise of the creation is resolved. So calling connectDB multiple times will have database === undefined each time.

You should cache the creation-promise and return that from connectDB if it already exists.

Instead of

if (database) return database;
database = await RxDB.create({
    name: 'fruitsdb',
    adapter: leveldown,
    password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
});

do

if (database) return await database;
database = RxDB.create({
    name: 'fruitsdb',
    adapter: leveldown,
    password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
});

I was missing an await in tree.mjs . The line (await model()).create(Fruit); should be await (await model()).create(Fruit); the inner await was throwing me off. Now it's behaving like I expected it to.

In Node.js global scope is equal to the files' own scope. If you want to define a global variable accesible by all files at runtime, useglobal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM