如何持有NodeJS应用程序,直到其他承诺完成

使用NodeJS的承诺,我加载了一个模型,然后通过后续调用NodeJS应用程序来重用。 如果第二个请求在第一个请求仍然被加载时到达,我怎样才能防止从数据库中加载两次相同的对象/模型?

我设置了一个“加载标志”来表示对象正在从数据库中检索,并在完成时“加载”。 如果有第二个请求尝试加载同一个对象,则需要等待,直到初始模型被填充,然后两者都可以使用同一个对象。

示例代码(简化,ES6,节点0.10 [有原因的旧])。

这是需要解决的TODO。

应用程序:

import ClickController from './controllers/ClickController' import express from 'express' const app = express() app.get('/click/*', (req, res) => { // Get the parameters here let gameRef = "test"; ClickController.getGameModel(gameRef) .then(() => { console.log('Got game model') return this.handleRequest() }, (err) => { throw err }) } 

控制器:

 import gameModel from '../models/GameModel' class ClickController { constructor(config) { // Stores the objects so they can be re-used multiple times. this.loadedGames = {} } // getGameModel() as a promise; return model (or throw error if it doesn't exist) getGameModel(gameRef) { return new Promise((resolve, reject) => { let oGame = false if(typeof this.loadedGames[gameRef] === 'undefined') { oGame = new gameModel() this.loadedGames[gameRef] = oGame } else { oGame = this.loadedGames[gameRef] } oGame.load(gameRef) .then(function() { resolve() }, (err) => { reject(err) }) }) } } 

型号/对象:

 class GameModel { constructor { this.loading = false this.loaded = false } load(gameRef) { return new Promise((resolve, reject) => { if (this.loading) { // TODO: Need to wait until loaded, then resolve or reject } else if (!this.loaded) { this.loading = true this.getActiveDBConnection() .then(() => { return this.loadGame(gameRef) }, (err) => { console.log(err) reject(err) }) .then(() => { this.loading = false this.loaded = true resolve() }) } else { // Already loaded, we're fine resolve() } }) } // As this uses promises, another event could jump in and call "load" while this is working loadGame(gameRef) { return new Promise((resolve, reject) => { let sql = `SELECT ... FROM games WHERE gameRef = ${mysql.escape(gameRef)}` this.dbConnection.query(sql, (err, results) => { if (err) { reject('Error querying db for game by ref') } else if (results.length > 0) { // handle results resolve() } else { reject('Game Not Found') } }) }) } } 

我并没有完全按照你所问的代码来确定你的代码是哪一部分,但是当一个请求已经是“正在进行中”的时候,用一个承诺caching一个值的通常scheme是这样的:

 var cachePromise; function loadStuff(...) { if (cachePromise) { return cachePromise; } else { // cache this promise so any other requests while this one is stil // in flight will use the same promise cachePromise = new Promise(function(resolve, reject) { doSomeAsyncOperation(function(err, result) { // clear cached promise so subsequent requests // will do a new request, now that this one is done cachePromise = null; if (err) { reject(err); } else { resolve(result); } }); }); return cachePromise; } } // all these will use the same result that is in progress loadStuff(...).then(function(result) { // do something with result }); loadStuff(...).then(function(result) { // do something with result }); loadStuff(...).then(function(result) { // do something with result }); 

这保留了caching的承诺,只要请求是“ cachePromise ”, cachePromise值就位,并将由后续请求返回。

只要请求实际完成, cachePromise将被清除,以便稍后发出的下一个请求将发出新的请求。