direflow icon indicating copy to clipboard operation
direflow copied to clipboard

`DireflowPromiseAlike` does not properly scope resolutions

Open joelash opened this issue 4 years ago • 3 comments

I was looking at the example about using redux with the callbacks on the two different components. When I something similar I noticed only the last of the .then bodies was being called. I used the Code Sandbox example and realized that this was broken as of v.3.5.x. You can see that on this updated example.

Digging though the code I've narrowed it down to the following lines in DireflowComponent.tsx and the fact that there is only one instance of_resolve and callback.

I've tried to fix this on a forked branch, please take a look and let me know your thoughts.

joelash avatar Sep 23 '21 02:09 joelash

I just using one subclass to replace with DireflowComponent

import { DireflowComponent as DireflowComponentBase } from 'direflow-component';

export function Dispatcher () {
  let listeners = []
  return {
    subscribe(listener) {
      listeners.push(listener)
      return () => listeners = listeners.filter((l) => l !== listener)
    },
    dispatch(data) {
      listeners.forEach((l) => l(data))
    }
  }
}

const d = Dispatcher()

export default class DireflowComponent extends DireflowComponentBase {
  static create(config) {
    const tagname = config.configuration.tagname
    const component = super.create(config)

    component.then(d.dispatch)

    return new Promise(resolve => {
      d.subscribe((element) => {
        if (element.tagName.toLowerCase() === tagname) {
          resolve(element)
        }
      })
    })
  }
}

lloydzhou avatar Mar 17 '22 17:03 lloydzhou

@joelash

support multi instance

import { DireflowComponent as DireflowComponentBase } from 'direflow-component';

export function Dispatcher () {
  let listeners = []
  return {
    subscribe(listener) {
      listeners.push(listener)
      return () => listeners = listeners.filter((l) => l !== listener)
    },
    dispatch(data) {
      listeners.forEach((l) => l(data))
    }
  }
}

const d = Dispatcher()

export default class DireflowComponent extends DireflowComponentBase {
  static create(config) {
    const tagname = config.configuration.tagname
    const component = super.create(config)

    component.then(d.dispatch)

    const subscribe = (resolve, id) => {
      d.subscribe((element) => {
        if (element.tagName.toLowerCase() === tagname) {
          if (!id || (id && id === element.id)) {
            resolve(element)
          }
        }
      })
    }
    const p = new Promise(resolve => subscribe(resolve))
    // return Promise instance, and add subscribe function, can call multi time when multi instance mounted
    p.subscribe = subscribe
    return p
  }
}

using id to filter instance

// index.html 
<direflow-component id="example1"></direflow-component>
<direflow-component id="example2"></direflow-component>

// index.js
DireflowExample.subscribe((example1) => {
  console.log('example1 mounted', example1)
}, "example1")
DireflowExample.subscribe((example2) => {
  console.log('example2 mounted', example2)
}, "example2")

lloydzhou avatar Mar 18 '22 02:03 lloydzhou

@lloydzhou Thank you for this fix! It works now again... BUT now the eventListeners are only added to the first instance of the custom-elements.

to stay with the redux example, try this:

<item-list-conmponent id="example1"></item-list-conmponent>
<item-add-conmponent id="example2"></item-add-conmponent>
<item-list-conmponent id="example3"></item-list-conmponent>
<item-add-conmponent id="example4"></item-add-conmponent>

Only the first two will work... the others don`t have eventListeners...

m4m-simon avatar Apr 22 '22 15:04 m4m-simon