javascript - 在nodejs中实例化对象时防止踩踏

标签 javascript node.js semaphore

当我在 NodeJS 中使用 Google Cloud 服务时,我必须访问存储桶(在存储中)等资源,并且第一次调用它们时,我必须检查它们是否存在,如果不存在,则创建它们。

好吧,如果多个资源在应用程序启动时访问同一个存储桶,它们将尝试同时创建它。

为了防止踩踏,我必须使用这样的东西:

getStorage(id) {
    return new Promise((resolve, reject) => {

        // Exists storage?
        if(id in this.storage) {
            let storage = this.storage[id];

            // Storage is ready, deliver
            if(storage.ready) {
                return resolve(storage);
            }

            // Not ready, wait until storage is ready
            let wait;
            let start = +Date.now();

            wait = setInterval(() => {
                // Storage is now ready
                if(storage.ready) {
                    clearInterval(wait);
                    return resolve(storage);
                }

                // Timeout in 15 seconds
                if(+Date.now() - start > 15*1000) {
                    clearInterval(wait);
                    return reject(new Error('timeout while waiting storage creation'));
                }
            }, 10);

            return;
        }

        // Start storage creation
        let storage = new Storage(id);

        this.storage[id] = storage;

        storage
            .create()
            .then(resolve, reject);
    });
}

lodash、下划线或异步中是否有任何内容可以帮助解决这种情况?实例踩踏场景。

信号量会有用吗?

在异步风格中,它可能是这样的:

getStorage(id) {
    return new Promise((resolve, reject) => {
        // already found
        if(id in this.storage) {
            resolve(this.storage[id]);
            return;
        }

        // prevent stampede

        // async.stampede( UNIQUE_ID, CREATE, RESULT )
        // - CREATE will be called once for UNIQUE_ID

        async.stampede(id, (end) => {
            let storage = new Storage(id);

            storage
                .create()
                .then(
                    () => end(null, storage),
                    (err) => end(err)
                );

        }, (err, result) => {
            if(err) reject(err);
            else {
                this.storage[id] = storage;
                resolve(result);
            }
        });
    });
}

在 lodash 中,它可以是类似“一次”的东西,但带有 promise 。

最佳答案

您不需要任何信号量或对 promise 进行特殊处理。 Promise 是表示异步结果的值,您可以直接缓存它们。您不需要“类似”一次,您想要完全一次。您不再需要任何东西。

或者实际上,由于您想根据 id 参数缓存它们,因此您需要使用 memoize来自 Underscore/Lodash:

getStorage: _.memoize(id => new Storage(id).create())

或者在没有库的情况下编写,

getStorage(id) {
    // Exists storage?
    if (id in this.storage) {
        return this.storage[id]; // it's a promise
    } else {
        // Start storage creation
        let storage = new Storage(id);
        let promise = storage.create();
        this.storage[id] = promise; // store the promise!
        return promise;
    }
}

确保避免 Promise constructor antipattern !

关于javascript - 在nodejs中实例化对象时防止踩踏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41085713/

相关文章:

javascript - 我试图将我的 sportsPerson 格式化为仅大写的第一个字母

node.js - 将 pm2 日志从 ec2 实例发送到 cloudwatch

node.js - 向REDIS中插入数据(node.js + redis)

c++ - UNIX/OSX 版本的 semtimedop

javascript - CSS 类在动态添加的选择框中不起作用

c# - 将数据作为字符串从C#发送到Javascript-如何检查字符串?

Python信号量永远挂起

c - 为什么我的信号量允许 fork 进程中的乱序事件?

javascript - 服务器的安全 ajax GET/POST 请求

mysql - My SQL 数据库 Sequelize npm