Fixing loop when setting variables
Setting a variable would makes the application enter in an infinite loop of events (between all the scripts and the back) This fix makes sure a variable does not emit any event if it is changed to a value it already has.
This commit is contained in:
parent
84df25f863
commit
2aba6b1c27
6 changed files with 61 additions and 23 deletions
|
@ -32,9 +32,9 @@ import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
|
|||
import { isLoadPageEvent } from "./Events/LoadPageEvent";
|
||||
import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent";
|
||||
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
||||
import { isSetVariableIframeEvent, SetVariableEvent } from "./Events/SetVariableEvent";
|
||||
import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
||||
|
||||
type AnswererCallback<T extends keyof IframeQueryMap> = (query: IframeQueryMap[T]['query']) => IframeQueryMap[T]['answer']|PromiseLike<IframeQueryMap[T]['answer']>;
|
||||
type AnswererCallback<T extends keyof IframeQueryMap> = (query: IframeQueryMap[T]["query"], source: MessageEventSource | null) => IframeQueryMap[T]["answer"] | PromiseLike<IframeQueryMap[T]["answer"]>;
|
||||
|
||||
/**
|
||||
* Listens to messages from iframes and turn those messages into easy to use observables.
|
||||
|
@ -187,7 +187,7 @@ class IframeListener {
|
|||
};
|
||||
|
||||
try {
|
||||
Promise.resolve(answerer(query.data)).then((value) => {
|
||||
Promise.resolve(answerer(query.data, message.source)).then((value) => {
|
||||
iframe?.contentWindow?.postMessage({
|
||||
id: queryId,
|
||||
type: query.type,
|
||||
|
@ -197,18 +197,6 @@ class IframeListener {
|
|||
} catch (reason) {
|
||||
errorHandler(reason);
|
||||
}
|
||||
|
||||
if (isSetVariableIframeEvent(payload.query)) {
|
||||
// Let's dispatch the message to the other iframes
|
||||
for (iframe of this.iframes) {
|
||||
if (iframe.contentWindow !== message.source) {
|
||||
iframe.contentWindow?.postMessage({
|
||||
'type': 'setVariable',
|
||||
'data': payload.query.data
|
||||
}, '*');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isIframeEventWrapper(payload)) {
|
||||
if (payload.type === "showLayer" && isLayerEvent(payload.data)) {
|
||||
this._showLayerStream.next(payload.data);
|
||||
|
@ -439,6 +427,21 @@ class IframeListener {
|
|||
public unregisterAnswerer(key: keyof IframeQueryMap): void {
|
||||
delete this.answerers[key];
|
||||
}
|
||||
|
||||
dispatchVariableToOtherIframes(key: string, value: unknown, source: MessageEventSource | null) {
|
||||
// Let's dispatch the message to the other iframes
|
||||
for (const iframe of this.iframes) {
|
||||
if (iframe.contentWindow !== source) {
|
||||
iframe.contentWindow?.postMessage({
|
||||
'type': 'setVariable',
|
||||
'data': {
|
||||
key,
|
||||
value,
|
||||
}
|
||||
}, '*');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const iframeListener = new IframeListener();
|
||||
|
|
|
@ -23,11 +23,11 @@ export const initVariables = (_variables: Map<string, unknown>): void => {
|
|||
|
||||
setVariableResolvers.subscribe((event) => {
|
||||
const oldValue = variables.get(event.key);
|
||||
|
||||
// If we are setting the same value, no need to do anything.
|
||||
if (oldValue === event.value) {
|
||||
// No need to do this check since it is already performed in SharedVariablesManager
|
||||
/*if (JSON.stringify(oldValue) === JSON.stringify(event.value)) {
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
variables.set(event.key, event.value);
|
||||
const subject = variableSubscribers.get(event.key);
|
||||
|
|
|
@ -54,7 +54,7 @@ export class SharedVariablesManager {
|
|||
});
|
||||
|
||||
// When a variable is modified from an iFrame
|
||||
iframeListener.registerAnswerer("setVariable", (event) => {
|
||||
iframeListener.registerAnswerer("setVariable", (event, source) => {
|
||||
const key = event.key;
|
||||
|
||||
const object = this.variableObjects.get(key);
|
||||
|
@ -82,10 +82,18 @@ export class SharedVariablesManager {
|
|||
throw new Error(errMsg);
|
||||
}
|
||||
|
||||
// Let's stop any propagation of the value we set is the same as the existing value.
|
||||
if (JSON.stringify(event.value) === JSON.stringify(this._variables.get(key))) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._variables.set(key, event.value);
|
||||
|
||||
// Dispatch to the room connection.
|
||||
this.roomConnection.emitSetVariableEvent(key, event.value);
|
||||
|
||||
// Dispatch to other iframes
|
||||
iframeListener.dispatchVariableToOtherIframes(key, event.value, source);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue