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

这是我所拥有的功能:

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

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

问题在于,显然notASinglton in中的诺言可能是同时执行的,并且假设它们并行运行,那么所有承诺的执行上下文都是dbConnected = false

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

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

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

注2:另一个可能相关的问题:https://eslint.org/docs/rules/require-atomic-updates#rule-details

lshongbo 回答:在JavaScript中创建可靠的异步单例模式是不可能的吗?

  

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

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

  

所有这些对象的执行上下文将为dbConnected = false

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

本文链接:https://www.f2er.com/3079034.html

大家都在问