如何避免这种情况"竞争条件"?

时间:2018-02-04 13:23:15

标签: javascript

我不知道这可能在技术上被称为竞争条件......

我拥有的是一个大宝宝,它当时只能执行一个动作,但它是从api端点调用的;所以可以同时进行呼叫

我认为我需要做的是以某种方式创建一个操作队列,向创建它的人返回一个承诺,同步执行操作,并使用操作返回的值解析promise

以下是代码(它不是真正的btw,只是代表问题的代码段):

class Baby {
  constructor() {
    this.current = 'A'
  }

  go(from, to) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (from === this.current) {
          this.current = to
          resolve()
        } else {
          reject(new Error('Unexpected state'))
        }
      }, 100)
    })
  }

  // In order to perform the action successfully it has to do some steps in some exact order
  async doAction() {
    await this.go('A', 'B')
    await this.go('B', 'C')
    await this.go('C', 'A')

    console.log('OK')
  }
}

module.exports = new Baby()

并且这样称呼:

const baby = require('./baby')

for (let i = 0; i < 5; i++) {
  doAction()
}

提前致谢!

1 个答案:

答案 0 :(得分:0)

感谢Bergi的提示,这是最终解决方案:

基本上,这会保留一系列承诺,当需要添加新动作时,它会链接到当前的承诺链

const baby = {
  current: 'A',
  action: Promise.resolve(),

  go(from, to) { 
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (from === this.current) {
          this.current = to
          resolve()
        } else {
          reject(new Error('Unexpected state'))
        }
      }, 100)
    })
  },

  doAction() {
    this.action = this.action.then(async () => {
      await this.go('A', 'B')
      await this.go('B', 'C')
      await this.go('C', 'A')

      console.log('OK')
    })
  }
}


baby.doAction()
baby.doAction()
baby.doAction()