是否不可能在JavaScript中创建可靠的异步单例模式?

问题描述 投票:0回答:1

这是我所拥有的功能:

let counter = 0;
let dbConnected = false;

async function notASingleton(params) {
    if (!dbConnected) {
        await new Promise(resolve => {
            if (Math.random() > 0.75) throw new Error();
            setTimeout((params) => {
                dbConnected = true; // assume we use params to connect to DB
                resolve();
            }, 1000);
        });
        return counter++
    }
};
// in another module that imports notASingleton
Promise.all([notASingleton(params), notASingleton(params), notASingleton(params), notASingleton(params)]);

// in another module that imports notASingleton
notASingleton(params);
notASingleton(params);
notASingleton(params);
notASingleton(params);

问题是,notASinglton中的Promise.all承诺显然可以根据系统同时执行:“在某些计算机上,它们可以并行执行,或者在某种意义上可以同时执行,而在其他计算机上,它们可以执行。连续。”:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

假设它们并行运行,所有它们的执行上下文将为dbConnected = false;我误读了MDN的说明吗?

注意:我知道我们可以引入一个新变量,例如initiatingDbConnection,而不是检查!dbConnected,而是检查!initiatingDbConnection;但是,只要并发意味着在Promise.all内部,承诺的上下文将是相同的,那将不会有任何改变。

该模式可以在例如Java通过利用JVM的约定创建类:https://stackoverflow.com/a/16106598/12144949

但是,即使Java实现也不能用于需要传递变量的用例:“客户端应用程序无法传递任何参数,因此我们无法重用它。例如,具有通用的singleton类用于客户端应用程序提供数据库服务器属性的数据库连接。”https://www.journaldev.com/171/thread-safety-in-java-singleton-classes-with-example-code

javascript asynchronous promise singleton race-condition
1个回答
0
投票

“在某些计算机上,它们可以并行执行,或者在某种意义上可以同时执行,而在其他计算机上,它们可以串行执行。”

该MDN描述是垃圾。我将其删除。 Promise.all不负责执行任何操作,并且无论如何都不能“执行” promise。它所做的就是等待其参数,您就是在数组中创建这些承诺的人。即使您省略了Promise.all并多次简单地调用notASingleton(),它们也会运行(并同时打开多个连接)。

它们的执行上下文均为dbConnected = false

是,但仅是因为您的dbConnected = true;超时,并且您在此之前再次调用notASingleton()。不是因为Promise.all有什么特别之处。

© www.soinside.com 2019 - 2024. All rights reserved.