关于使用“异步锁定”返回值的nodejs的问题

问题描述

我在 concurrency typescript 程序中使用了 async-lock 模块。 使用此方法时,我想在lock.acquire(...) {...}中返回结果,但是效果不佳。 如何返回值?如果有任何建议,我将不胜感激。谢谢!

public async getValue(key: string): Promise<any> {
    const base = this;
    lock.acquire(key,async function (done) {
        base.logger.info(`${key} lock enter`);
        if (!await base.myRepository.checkDBTable(key)) {
            const valueFromNetwork: number = await base.getValueFromNetwork(key);
            const initResult: MyEntity = await base.myRepository.initNonce(key,valueFromNetwork);
            if (!initResult) {
                throw new Error('initValue failed...');
            }
            base.logger.debug(JSON.stringify(initResult,null,4));
        }
        const valueFromDB: number = await base.myRepository.getValueFromDB(key);
        if (valueFromDB === -1 || valueFromDB === undefined) {
            throw new Error('getValueFromDB failed...');
        } else {
            const updateResult: MyEntity = await base.myRepository.updateValue(key,valueFromDB);
            if (!updateResult) {
                throw new Error('updateValue failed...');
            }
            base.logger.info(`${valueFromDB}`);
            base.logger.info(`${key} lock done`);
            done();
        }

// I'd like to return valueFromDB above.

    });
}

解决方法

您有两个选择:

  1. 您可以在lock.aquire周围实现包装器(建议这样做,因为它更易于阅读并且可以处理采集错误):
public async getValue(key: string): Promise<any> {
  const base = this;
  const done = await this.aquireLock(key);
  base.logger.info(`${key} lock enter`);
  if (!await base.myRepository.checkDBTable(key)) {
    const valueFromNetwork: number = await base.getValueFromNetwork(key);
    const initResult: MyEntity = await base.myRepository.initNonce(key,valueFromNetwork);
    if (!initResult) {
      throw new Error('initValue failed...');
    }
    base.logger.debug(JSON.stringify(initResult,null,4));
  }
  const valueFromDB: number = await base.myRepository.getValueFromDB(key);
  if (valueFromDB === -1 || valueFromDB === undefined) {
    throw new Error('getValueFromDB failed...');
  } else {
    const updateResult: MyEntity = await base.myRepository.updateValue(key,valueFromDB);
    if (!updateResult) {
      throw new Error('updateValue failed...');
    }
    base.logger.info(`${valueFromDB}`);
    base.logger.info(`${key} lock done`);
    done();
  }
  return valueFromDB;
}
private async aquireLock(key: string): Promise<() => void> {
  return new Promise((resolve,reject) => {
    lock.acquire(key,done => {
      resolve(done);
    },(err)=>{ // in case our aquire fails(times out,etc.)
      if(err){
        reject(err);
      }
    })
  })
}

Playground

  1. 或者,您可以使用函数构造函数(即使它是反模式):
getValue(key: string): Promise<any> {
  return new Promise((resolve,reject) => {
    const base = this;
    lock.acquire(key,async function (done) {
      base.logger.info(`${key} lock enter`);
      if (!await base.myRepository.checkDBTable(key)) {
        const valueFromNetwork: number = await base.getValueFromNetwork(key);
        const initResult: MyEntity = await base.myRepository.initNonce(key,valueFromNetwork);
        if (!initResult) {
          reject(new Error('initValue failed...'));
        }
        base.logger.debug(JSON.stringify(initResult,4));
      }
      const valueFromDB: number = await base.myRepository.getValueFromDB(key);
      if (valueFromDB === -1 || valueFromDB === undefined) {
        reject(new Error('getValueFromDB failed...'));
      } else {
        const updateResult: MyEntity = await base.myRepository.updateValue(key,valueFromDB);
        if (!updateResult) {
          reject(new Error('updateValue failed...'));
        }
        base.logger.info(`${valueFromDB}`);
        base.logger.info(`${key} lock done`);
        done();
      }
      resolve(valueFromDB)
    });
  })
}

Playground(很多事情都已经搁置了,但是可以理解整个想法)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...