Vonage/rxzu

Cannot find Node element with node id directly after creation

Closed this issue · 2 comments

In the unit tests we sometimes get timing issues. And I also recognized this in our application.
When adding nodes like this:

const node = new BaseNodeModel({
          type: type,
          coords
        });
this.diagramModel.addNode(node);

and directly afterwards calling node.getTargetPort() or node.selectCoords() for instance, we sometimes get the error that an element with some id cannot be found.

Is this a bug or how should we handle this?

this is the full error message from ci build

Error: Cannot find Node element with node id: [c8802a14-66fb-4376-b612-74f6f17f2512]
	    at DiagramEngine.getNodeElement (node_modules/@rxzu/core/src/lib/engine.core.js:51:1)
	    at node_modules/@rxzu/core/src/lib/engine.core.js:222:1
	    at <Jasmine>
	    at DiagramEngine.getNodeLayersRect (node_modules/@rxzu/core/src/lib/engine.core.js:218:1)
	    at SafeSubscriber._next (node_modules/@rxzu/core/src/lib/engine.core.js:278:1)
	    at SafeSubscriber.__tryOrUnsub (node_modules/rxjs/_esm2015/internal/Subscriber.js:183:1)
	    at SafeSubscriber.next (node_modules/rxjs/_esm2015/internal/Subscriber.js:122:1)
	    at Subscriber._next (node_modules/rxjs/_esm2015/internal/Subscriber.js:72:1)
	    at Subscriber.next (node_modules/rxjs/_esm2015/internal/Subscriber.js:49:1)
	    at Notification.observe (node_modules/rxjs/_esm2015/internal/Notification.js:20:1)

I further investigated this and I think this is related to how nodes are created and added to the diagram.
In the core diagram.model.ts
add node is defined like this:

  addNode(node: NodeModel): NodeModel {
    this.nodes$.add(node).emit();
    return node;
  }

and emit is defined in value.state.ts like this:

  emit(): void {
    this.stream$.next(this.value);
  }

so this is an behaviour subject, but the addNode() returns the node independently from the next() on the subject. Therefore it can happen, that the node is used before it is added to the diagram via next()
We solve this by adding a rxjs delay(0) for getting a context switch.

@florianeichin since the view takes time to render everything, the painted property/observable will emit after the element is rendered and this can be used for testing