Skip to content

Commit 5b202f8

Browse files
Database once() should only fire once (#4864)
1 parent 3cd42d4 commit 5b202f8

File tree

5 files changed

+50
-2
lines changed

5 files changed

+50
-2
lines changed

.changeset/many-turtles-try.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/database": patch
3+
---
4+
5+
Fixed an issue that could cause `once()` to fire more than once if the value was modified inside its callback.

packages/database/src/api/Reference.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ export class Query implements Compat<ExpQuery> {
326326
validateCallback('Query.once', 'callback', callback, true);
327327

328328
const ret = Query.getCancelAndContextArgs_(
329-
'Query.on',
329+
'Query.once',
330330
failureCallbackOrContext,
331331
context
332332
);

packages/database/src/exp/Reference_impl.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,8 @@ function addEventListener(
959959
if (options && options.onlyOnce) {
960960
const userCallback = callback;
961961
const onceCallback: UserCallback = (dataSnapshot, previousChildName) => {
962-
userCallback(dataSnapshot, previousChildName);
963962
repoRemoveEventCallbackForQuery(query._repo, query, container);
963+
userCallback(dataSnapshot, previousChildName);
964964
};
965965
onceCallback.userCallback = callback.userCallback;
966966
onceCallback.context = callback.context;

packages/database/test/helpers/EventAccumulator.ts

+17
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ export const EventAccumulatorFactory = {
2727
count++;
2828
});
2929
return ea;
30+
},
31+
waitsForExactCount: maxCount => {
32+
let count = 0;
33+
const condition = () => {
34+
if (count > maxCount) {
35+
throw new Error('Received more events than expected');
36+
}
37+
return count === maxCount;
38+
};
39+
const ea = new EventAccumulator(condition);
40+
ea.onReset(() => {
41+
count = 0;
42+
});
43+
ea.onEvent(() => {
44+
count++;
45+
});
46+
return ea;
3047
}
3148
};
3249

packages/database/test/query.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -2330,6 +2330,32 @@ describe('Query Tests', () => {
23302330
await ea.promise;
23312331
});
23322332

2333+
it('Query.once() only fires once', async () => {
2334+
const node = getRandomNode() as Reference;
2335+
2336+
let count = 1;
2337+
node.set(count);
2338+
2339+
const valueEvent = EventAccumulatorFactory.waitsForCount(3);
2340+
node.on('value', () => {
2341+
if (count < 3) {
2342+
++count;
2343+
node.set(count);
2344+
}
2345+
valueEvent.addEvent();
2346+
});
2347+
2348+
const onceEvent = EventAccumulatorFactory.waitsForExactCount(1);
2349+
node.once('value', () => {
2350+
++count;
2351+
node.set(count);
2352+
onceEvent.addEvent();
2353+
});
2354+
2355+
await valueEvent.promise;
2356+
await onceEvent.promise;
2357+
});
2358+
23332359
it('Ensure on() returns callback function.', () => {
23342360
const node = getRandomNode() as Reference;
23352361
const callback = function () {};

0 commit comments

Comments
 (0)