mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Fix for linking issue.
Summary: If linking state changes multiple times frequently the code that simulates async operation is wrongly debounced, which causes inverted order of execution. This fix makes sure that only the last call to filter function is used. Test Plan: Adding new test Reviewers: alexmojaki Reviewed By: alexmojaki Subscribers: alexmojaki Differential Revision: https://phab.getgrist.com/D4139
This commit is contained in:
@@ -117,28 +117,16 @@ export class QuerySetManager extends Disposable {
|
||||
* RowSource.
|
||||
*/
|
||||
export class DynamicQuerySet extends RowSource {
|
||||
/**
|
||||
* Replace the query represented by this DynamicQuerySet. If multiple makeQuery() calls are made
|
||||
* quickly (while waiting for the server), cb() may only be called for the latest one.
|
||||
*
|
||||
* If there is an error fetching data, cb(err) will be called with that error. The second
|
||||
* argument to cb() is true if any data was changed, and false if not. Note that for a series of
|
||||
* makeQuery() calls, cb() is always called at least once, and always asynchronously.
|
||||
*
|
||||
* It's possible for this to be called very quickly in succession,
|
||||
* e.g. when selecting another row of a linked summary table grouped by multiple columns,
|
||||
* as an observable gets triggered for each one.
|
||||
* We only want to keep the last call, and _updateQuerySetDebounced may not be called
|
||||
* in the correct order, so we first debounce here.
|
||||
*/
|
||||
public readonly makeQuery = debounce(tbind(this._makeQuery, this), 0);
|
||||
|
||||
// Holds a reference to the currently active QuerySet.
|
||||
private _holder = Holder.create<IRefCountSub<QuerySet>>(this);
|
||||
|
||||
// Shortcut to _holder.get().get().
|
||||
private _querySet?: QuerySet;
|
||||
|
||||
// A ticket number for the latest makeQuery() call. We use it to avoid calling cb() for
|
||||
// superseded queries.
|
||||
private _lastTicket = 0;
|
||||
|
||||
// We could switch between several different queries quickly. If several queries are done
|
||||
// fetching at the same time (e.g. were already ready), debounce lets us only update the
|
||||
// query-set once to the last query.
|
||||
@@ -163,19 +151,26 @@ export class DynamicQuerySet extends RowSource {
|
||||
return this._querySet ? this._querySet.isTruncated : false;
|
||||
}
|
||||
|
||||
private _makeQuery(filters: { [colId: string]: any[] },
|
||||
operations: {[colId: string]: QueryOperation},
|
||||
cb: (err: Error|null, changed: boolean) => void): void {
|
||||
if (this.isDisposed()) {
|
||||
cb(new Error('Disposed'), false);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Replace the query represented by this DynamicQuerySet. If multiple makeQuery() calls are made
|
||||
* quickly (while waiting for the server), cb() may only be called for the latest one.
|
||||
*
|
||||
* If there is an error fetching data, cb(err) will be called with that error. The second
|
||||
* argument to cb() is true if any data was changed, and false if not. Note that for a series of
|
||||
* makeQuery() calls, cb() is always called at least once, and always asynchronously.
|
||||
*/
|
||||
public makeQuery(filters: {[colId: string]: any[]},
|
||||
operations: {[colId: string]: QueryOperation},
|
||||
cb: (err: Error|null, changed: boolean) => void): void {
|
||||
const query: ClientQuery = {tableId: this._tableModel.tableData.tableId, filters, operations};
|
||||
const newQuerySet = this._querySetManager.useQuerySet(this._holder, query);
|
||||
const ticket = this._getTicket();
|
||||
|
||||
// CB should be called asynchronously, since surprising hard-to-debug interactions can happen
|
||||
// if it's sometimes synchronous and sometimes not.
|
||||
newQuerySet.fetchPromise.then(() => {
|
||||
// Only if we weren't superseded by another query.
|
||||
if (!ticket.isValid()) { return; }
|
||||
this._updateQuerySetDebounced(newQuerySet, cb);
|
||||
})
|
||||
.catch((err) => { cb(err, false); });
|
||||
@@ -201,6 +196,13 @@ export class DynamicQuerySet extends RowSource {
|
||||
cb(err, true);
|
||||
}
|
||||
}
|
||||
|
||||
private _getTicket() {
|
||||
const myTicket = ++this._lastTicket;
|
||||
return {
|
||||
isValid: () => this._lastTicket === myTicket
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user