问题描述
我在 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.
});
}
解决方法
您有两个选择:
- 您可以在
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);
}
})
})
}
- 或者,您可以使用函数构造函数(即使它是反模式):
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(很多事情都已经搁置了,但是可以理解整个想法)