Javascript 如何为需要原子化的代码应用Promise.resolve

Javascript 如何为需要原子化的代码应用Promise.resolve,javascript,promise,atomic,Javascript,Promise,Atomic,我在一个合作伙伴经理和一些代码需要原子,因为目前有竞争条件,无法工作时,两个客户端调用相同的资源在同一时间。retrievePartners方法返回partners,该方法应该是原子的。基本合作伙伴是有限的资源,提供机制一次只能处理一个客户(请求合作伙伴) 我被告知下面的代码适用于原子操作,因为javascript是本机原子的 let processingQueue = Promise.resolve(); function doStuffExclusively() { processi

我在一个合作伙伴经理和一些代码需要原子,因为目前有竞争条件,无法工作时,两个客户端调用相同的资源在同一时间。retrievePartners方法返回partners,该方法应该是原子的。基本合作伙伴是有限的资源,提供机制一次只能处理一个客户(请求合作伙伴)

我被告知下面的代码适用于原子操作,因为javascript是本机原子的

let processingQueue = Promise.resolve();

function doStuffExclusively() {

  processingQueue = processingQueue.then(() => {
      return fetch('http://localhost', {method: 'PUT', body: ...});
  }).catch(function(e){
      throw e;
  });

  return processingQueue;
}

doStuffExclusively()
doStuffExclusively()
doStuffExclusively()
然而,这段代码是基本的,我的代码有一些wait调用另一个wait,等等。我想在下面的代码中应用这种机制,但我真的不知道怎么做,我尝试了一些技巧,但没有效果。无法在then语句中获取等待工作

我还感到困惑的是,上面的代码在processingQueue的那个部分返回true。但是在我的例子中,我返回一个数组,或者抛出一条错误消息。我应该退回一些东西让它像上面那样工作吗

这是我想让原子化的函数,就像上面的代码一样。我试图在返回语句之前,将函数中的所有内容都放在then部分中,但没有成功,因为

export class Workout {
  constructor (config) {
    this.instructorPeer = new jet.Peer(config)
    this.instructorPeer.connect()
  }

  async createSession (partnerInfo) {
    const partners = { chrome: [], firefox: [], safari: [], ie: [] }
    const appropriatePartners = await this.retrievePartners(partnerInfo)
    Object.keys(appropriatePartners).forEach(key => {
      appropriatePartners[key].forEach(partner => {
        const newPartner = new Partner(this.instructorPeer, partner.id)
        partners[key].push(newPartner)
      })
    })

    return new Session(partners)
  }
  async retrievePartners (capabilities) {
    const appropriatePartners = { chrome: [], firefox: [], safari: [], ie: [] }
    const partners = await this.getAllPartners()

    // first check if there is available appropriate Partners
    Object.keys(capabilities.type).forEach(key => {
      let typeNumber = parseInt(capabilities.type[key])
      for (let i = 0; i < typeNumber; i++) {
        partners.forEach((partner, i) => {
          if (
            key === partner.value.type &&
            partner.value.isAvailable &&
            appropriatePartners[key].length < typeNumber
          ) {
            appropriatePartners[key].push(partner)
            console.log(appropriatePartners[key].length)
          }
        })

        if (appropriatePartners[key].length < typeNumber) {
          throw new Error(
            'Sorry there are no appropriate Partners for this session'
          )
        }
      }
    })

    Object.keys(appropriatePartners).forEach(key => {
      appropriatePartners[key].forEach(partner => {
        this.instructorPeer.set('/partners/' + partner.id + '/states/', {
          isAvailable: false
        })
      })
    })

    return appropriatePartners
  }

  async getAllPartners (capabilities) {
    const partners = []
    const paths = await this.instructorPeer.get({
      path: { startsWith: '/partners/' }
    })
    paths.forEach((path, i) => {
      if (path.fetchOnly) {
        let obj = {}
        obj.value = path.value
        obj.id = path.path.split('/partners/')[1]
        obj.value.isAvailable = paths[i + 1].value.isAvailable
        partners.push(obj)
      }
    })
    return partners
  }
这是我尝试过的,但没有成功,会话并没有定义

let processingQueue = Promise.resolve()

    export class Workout {
  constructor (config) {
    this.instructorPeer = new jet.Peer(config)
    this.instructorPeer.connect()
this.processingQueue = Promise.resolve()
  }

  async createSession (partnerInfo) {
    this.processingQueue = this.processingQueue.then(() => {
      const partners = { chrome: [], firefox: [], safari: [], ie: [] }
      const appropriatePartners = this.retrievePartners(partnerInfo)
      Object.keys(appropriatePartners).forEach(key => {
        appropriatePartners[key].forEach(partner => {
          const newPartner = new Partner(this.instructorPeer, partner.id)
          partners[key].push(newPartner)
        })
      })

      return new Session(partners)
    })
  }

这是基于承诺的锁定,基于以下事实:

1) 只有在解除锁定后才会调用
.then()
处理程序

2) 一旦
.then()
处理程序开始执行,由于JS的执行模型,将不会执行其他JS代码

你所引用的方法的总体结构是正确的

我在代码中看到的主要问题是
constpropertypartners=this.retrievePartners(partnerInfo)
将评估为承诺,因为
retrievePartners
是异步的。您想:

constpropertypartners=等待此消息。检索合作伙伴(partnerInfo)

这将导致锁的执行器阻塞
retrievePartners
调用,而当前您只是获取一个包含该调用最终返回值的承诺

编辑:有关示例,请参见

总之:

1) 使箭头函数处理锁定分辨率
异步


2) 确保它等待
this.retrievePartners
的返回值,否则您将按照承诺操作,而不是按照解析值操作。

这是客户端Javascript的服务器端吗?我猜这是某种节点服务?可能重复的
constpartners=wait this.getAllPartners()
我认为应该是
constpartners=return this.getAllPartners()
。。由于它位于异步?getAllPartners返回系统中的所有伙伴,无论是否可用。其他帖子可能与此类似,但我想问的是,如何为我的代码实现锁代码?旁注:以这种方式定义的catch()调用与根本没有catch的调用基本相同。感谢Jagthe甲壳虫提供的详细答案,我仍然很困惑,你建议我做什么?首先,我认为在您的retrievePartners呼叫中添加Wait是必要的。旁注,但这只在一个JS运行时内实现锁定(因此,如果我了解您的设置,服务器必须代表客户端执行此操作)。我看到您也编写了方法getAllPartners,实际上它是一个方法,只会将注册到node jet的所有合作伙伴响铃。我在原始帖子中添加了getAllPartners的代码。你能根据这个重写你的小提琴代码吗?你确定这行吗?我想在同一个等级库文件中使用相同训练对象的不同测试同时访问createSession。我以前的测试无法并行运行,因为它们试图同时获得相同的资源(合作伙伴)。我得到的训练不是你代码的构造器。。我看到你的构造函数没有接受parameter,你也写了新的Map,而不是new.Jet,它破坏了整个事情..我看到你在getAllPartners中实现了locked=true和locked=false,而不是retrievePartners。retrievePartners方法应该是原子的
let processingQueue = Promise.resolve()

    export class Workout {
  constructor (config) {
    this.instructorPeer = new jet.Peer(config)
    this.instructorPeer.connect()
this.processingQueue = Promise.resolve()
  }

  async createSession (partnerInfo) {
    this.processingQueue = this.processingQueue.then(() => {
      const partners = { chrome: [], firefox: [], safari: [], ie: [] }
      const appropriatePartners = this.retrievePartners(partnerInfo)
      Object.keys(appropriatePartners).forEach(key => {
        appropriatePartners[key].forEach(partner => {
          const newPartner = new Partner(this.instructorPeer, partner.id)
          partners[key].push(newPartner)
        })
      })

      return new Session(partners)
    })
  }