deepstream.io-client-js
deepstream.io-client-js copied to clipboard
record.whenReady triggers when document isn't ready yet
Versions:
- npm: @deepstream/client v4.1.3
- docker: deepstreamio/deepstream.io:latest
In this test the hello-world
record contains a simple object: {hello: 'world'}
. The test file:
const deepstream = require('@deepstream/client');
const client = deepstream('ws://localhost:6020');
client.login();
const record = client.record.getRecord('hello-world');
record.whenReady(() => {
console.log('event: whenReady', `ready: ${record.isReady}`, JSON.stringify(record.get()));
});
record.subscribe(() => {
console.log('event: subscribe', `ready: ${record.isReady}`, JSON.stringify(record.get()));
});
What I expected to see in my console is the following:
event: subscribe ready: false {}
event: whenReady ready: true {"hello": "world"}
event: subscribe ready: true {"hello": "world"}
But what I get is this:
The first log shows that record.isReady
is true
when it's clearly not. The second log is triggered by whenReady
but as you can see the document is still empty so it's not actually ready. The third log is a total mystery why it happens because nothing has changed since the first subscribe
event. Only in the fourth log the record
contains all the data from the server.
Question: How do I know when the record is truly ready?
What I'm doing for now is this "hack":
const deepstream = require("@deepstream/client");
const client = deepstream("ws://localhost:6020");
const stateMatchGroups = [
["MERGING", "READY"], // When using `record.getRecord` before being logged
["SUBSCRIBING", "READY"], // When `record.getRecord` yields an empty document
["RESUBSCRIBING", "READY"] // When using `record.getRecord` after being logged
];
function isActuallyReady(record) {
return record.record.stateMachine.history.some(state =>
stateMatchGroups.some(
([oldState, newState]) =>
state.oldState === oldState && state.newState === newState
)
);
}
function whenActuallyReady(record, callback) {
const listener = () => isActuallyReady(record) && setTimeout(callback, 0);
record.whenReady(listener);
record.subscribe(listener);
}
client.login();
const record = client.record.getRecord("hello-world");
whenActuallyReady(record, () => {
console.log(
"event: whenActuallyReady",
`ready: ${isActuallyReady(record)}`,
JSON.stringify(record.get())
);
});
I'm basically directly accessing the state machine to make sure that the record at least had some interactions with the server and tried merging things... Notice that I needed a setTimeout
there because there's a race condition somewhere in the client's logic where the callbacks for record.whenReady
and record.subscribe
are being called BEFORE the remote data gets merged.
Yeah your problem is that you are loading records while offline.
await client.login()
Should fix it. Offline disabled just means we don't set or store data in a local store. However record data is still stored in memory during connection loss and can be edited, which is why I can't disable some aspects and not others.
This functionality can only be disabled if you are in readOnly mode, since in that case you can't edit the data.
I need to look into why your subscribes are being called like that though!