如何在其他承诺完成之前保留NodeJS应用程序 [英] How to hold a NodeJS application until other promise completes

查看:78
本文介绍了如何在其他承诺完成之前保留NodeJS应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用NodeJS的promise,我加载了一个模型,然后可以通过对NodeJS应用程序的后续调用来重新使用该模型。如果在第二个请求仍在加载时第二个请求到达,如何防止同一对象/模型从数据库中加载两次?

Using promises with NodeJS, I load a model that can then be re-used by susequent calls to the NodeJS app. How can I prevent the same object/model being loaded twice from a database if a second request arrives while the first is still being loaded?

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

I set a "loading flag" to say that the object is being retrieved from the database and "loaded" when done. If there is a second request that attempts to load the same object, it needs to wait until the initial model is filled and then both can use the same object.

示例代码(简化为ES6,节点为0.10(由于某种原因而旧))。

Sample Code (simplified, ES6, Node 0.10 [old for a reason]).

这是需要解决的TODO。

It's the TODO that needs solving.

App:

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')
                }
            })

        })
    }
}


推荐答案

我并不确定您要查询的是代码的哪一部分,而是通常的方案是在一个请求已经是运行中,例如:

I don't follow exactly which part of you're code you are asking about, but the usual scheme for caching a value with a promise while a request is already "in-flight" works like this:

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
});

这会保留一个缓存的承诺,并且只要请求处于运行中状态, c $ c> cachePromise 值到位,并将由后续请求返回。

This keeps a cached promise and, as long as request is "in-flight", the cachePromise value is in place and will be returned by subsequent requests.

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

As soon as the request actually finishes, the cachePromise will be cleared so that the next request that comes later will issue a new request.

这篇关于如何在其他承诺完成之前保留NodeJS应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆