【问题标题】:How to synchronize a method in javascript?如何在javascript中同步一个方法?
【发布时间】:2023-01-16 06:08:44
【问题描述】:

我正在尝试同步一个单身人士。 我需要使此方法类似于 java 中的同步方法。 发生在我身上的是因为套接字需要一段时间,如果前两个请求非常接近,我会创建两个 websockets。 (然后从第三个开始它正确地接受了实例)。


import io from 'socket.io-client';

export default class SocketIo {
  static socket = null;

  static instance = null;

  async initialize() {
    this.socket = await io(`http://${ip}:10300/`, {
      transports: ['websocket'],
    });
  }

  static async getInstance() {
    logger.info('socketIo.api.getInstance: BEGIN');
    if (!this.instance) {
      logger.info('socketIo.api.getInstance: creating new socket instance...');
      try {
        const o = new SocketIo();
        await o.initialize();
        this.instance = o;
        logger.info('socketIo.api.getInstance: socket instance created SUCCESSFULLY');
      } catch (e) {
        moaLog('socketIo.api.getInstance: ERROR: ', e);
        throw e;
      }
    } else {
      logger.info('socketIo.api.getInstance: a socket instance already exists, reusing that one');
    }
    logger.info('socketIo.api.getInstance: END');
    return this.instance;
  }
}

在 main.js 中

var socket1 = SocketIo.getInstance();
var socket2 = SocketIo.getInstance();

// ... after a while
var socket3 = SocketIo.getInstance();



2022-06-16T17:53:40.658Z: socketIo.api.getInstance: BEGIN
2022-06-16T17:53:40.660Z: socketIo.api.getInstance: creating new socket instance...
2022-06-16T17:53:41.140Z: socketIo.api.getInstance: BEGIN
2022-06-16T17:53:41.141Z: socketIo.api.getInstance: creating new socket instance...
2022-06-16T17:53:41.379Z: socketIo.api.getInstance: socket instance created SUCCESSFULLY
2022-06-16T17:53:41.382Z: socketIo.api.getInstance: END
2022-06-16T17:53:41.411Z: socketIo.api.getInstance: socket instance created SUCCESSFULLY
2022-06-16T17:53:41.415Z: socketIo.api.getInstance: END
...
2022-06-16T17:56:13.076Z: socketIo.api.getInstance: BEGIN
2022-06-16T17:56:13.078Z: socketIo.api.getInstance: a socket instance already exists, reusing that one
2022-06-16T17:56:13.079Z: socketIo.api.getInstance: END

从服务器视图我看到两个 websocket 连接。

有任何想法吗?

【问题讨论】:

  • 什么是new SocketIo()?看起来不像图书馆的 API,无论是在客户端还是在服务器上。这是习俗吗? initialize 在内部做什么?
  • @WiktorZychla 我不确定这是否重要。调用create(); create(); 将生成两个SocketIo 对象并初始化它们,而不管SocketIo 本身的实现如何。假设 initialize() 是异步的是合理的,因此 await 在那里是合适的。
  • @WiktorZychla 感谢您的回复。更清楚地说,我用完整的课程代码编辑了我的问题。

标签: javascript singleton synchronized


【解决方案1】:

下面是尝试同步你的单例。这个想法是存储 o.intitialize promise 并检查它是否已经被获取。

我添加了一个uid,一个在initialize中设置的随机值,以表明只创建了单个实例。

class SocketIo {
    static instance = null;
    static _lock = null;

    async initialize() {
        this.uid = Math.random();
    }

    static async getInstance() {
        console.log('socketIo.api.getInstance: BEGIN');
        if (!this.instance) {
            console.log('socketIo.api.getInstance: creating new socket instance...');

            const o = new SocketIo();
            if (!this._lock) {
                this._lock = o.initialize();
                await this._lock;
                this.instance = o;
                console.log('socketIo.api.getInstance: socket instance created SUCCESSFULLY');
                this._lock = null;
            } else {
                await this._lock;
            }
        }
        console.log('socketIo.api.getInstance: END');
        return this.instance;
    }
}

async function Main() {
    var socket1 = SocketIo.getInstance();
    var socket2 = SocketIo.getInstance();

    console.log((await socket1).uid);
    console.log((await socket2).uid);
}

Main()

将其与您的版本进行比较:

class SocketIo {
    static instance = null;

    async initialize() {
        this.uid = Math.random();
    }

    static async getInstance() {
        console.log('socketIo.api.getInstance: BEGIN');
        if (!this.instance) {
            console.log('socketIo.api.getInstance: creating new socket instance...');

            const o = new SocketIo();
            await o.initialize();
            this.instance = o;
            console.log('socketIo.api.getInstance: socket instance created SUCCESSFULLY');
        }
        console.log('socketIo.api.getInstance: END');
        return this.instance;
    }
}

async function Main() {
    var socket1 = SocketIo.getInstance();
    var socket2 = SocketIo.getInstance();

    console.log((await socket1).uid);
    console.log((await socket2).uid);
}

Main()

希望这适合您。

【讨论】:

    【解决方案2】:

    我解决了使用异步锁。

    import AsyncLock from 'async-lock';
    const lock = new AsyncLock();
    
    export default class SocketIo {
      // ...
    
      static async getInstance() {
        logger.info('socketIo.api.getInstance: BEGIN');
        if (!this.instance) {
          logger.info('socketIo.api.getInstance: creating new socket instance...');
          try {
            await lock.acquire('socketIo', async () => {
              if (!this.instance) {
                const o = new SocketIo();
                await o.initialize();
                this.instance = o;
                logger.info('socketIo.api.getInstance: socket instance created SUCCESSFULLY');
              }
            });
          } catch (e) {
            moaLog('socketIo.api.getInstance: ERROR: ', e);
            throw e;
          }
        } else {
          logger.info('socketIo.api.getInstance: a socket instance already exists, reusing that one');
        }
        logger.info('socketIo.api.getInstance: END');
        return this.instance;
      }
    }

    【讨论】:

      猜你喜欢
      • 2012-03-20
      • 2010-11-11
      • 1970-01-01
      • 2011-01-15
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      相关资源
      最近更新 更多