Skip to content

Commit 3401e62

Browse files
author
CodeBuddy Attribution Bot
committed
fix(attribution): 实时监听 API 缺乏初始数据就绪通知机制 (issue_mnrzm5ru_70sm9m)
1 parent fe65ec0 commit 3401e62

4 files changed

Lines changed: 14 additions & 14 deletions

File tree

config/.claude/skills/no-sql-web-sdk/SKILL.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Keep local `references/...` paths for files that ship with the current skill dir
4646
- Querying before the user is signed in when the collection rules require identity.
4747
- Using `wx.cloud.database()` or Node SDK patterns in browser code.
4848
- Initializing CloudBase lazily with dynamic imports instead of a shared synchronous app instance.
49-
- For realtime UI, assuming the listener is ready immediately after calling `watch()`. Treat the first `onChange` snapshot whose `docChanges` contain `dataType: 'init'` as the initial data ready signal before rendering room state, enabling actions, or concluding that the query returned no rows.
49+
- For realtime UI, assuming the listener is ready immediately after calling `watch()`. Treat the first `onChange` snapshot whose `snapshot.type === 'init'` as the canonical initial data ready signal before rendering room state, enabling actions, or concluding that the query returned no rows.
5050
- Treating security rules as result filters rather than request validators.
5151
- For CMS-style collections that need **app-level admin users** to edit/delete all records while editors can only edit/delete their own records, do not oversimplify the rule to `READONLY`. A validated pattern is a `CUSTOM` rule that reads role from `user_roles` by `auth.uid` and combines it with `doc.authorId == auth.uid`, while frontend writes can stay on `.doc(id).update()` / `.doc(id).remove()`.
5252
- Forgetting pagination or indexes for larger collections.
@@ -122,7 +122,8 @@ Important rules:
122122

123123
5. **Handle realtime initialization explicitly**
124124
- `.watch()` becomes usable only after the first `onChange` snapshot arrives.
125-
- Use the snapshot whose `docChanges` include `dataType: 'init'` as the canonical "initial data is ready" event.
125+
- Use the snapshot whose `type` is `init` as the canonical "initial data is ready" event.
126+
- If you also inspect `docChanges`, the initial payload may include `dataType: 'init'`, but do not treat the query as ready before that first init snapshot arrives.
126127
- Until that event arrives, keep loading state explicit and avoid enabling turn-based actions that depend on the queried documents.
127128

128129
## Quick examples

config/.claude/skills/no-sql-web-sdk/realtime.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ Create a real-time data listener that returns a `watcher` object.
9292

9393
Calling `.watch()` only starts the listener setup. Do not assume the queried data is ready immediately after `watch()` returns.
9494

95-
- Treat the first `onChange` snapshot whose `docChanges` contain `dataType: 'init'` as the canonical "initial data is ready" signal.
95+
- Treat the first `onChange` snapshot whose `type` is `init` as the canonical "initial data is ready" signal.
96+
- The initial payload may also include `docChanges` items with `dataType: 'init'`, but the listener is not ready until that first init snapshot arrives.
9697
- Until that `init` snapshot arrives, keep loading state explicit.
9798
- Do not enable turn-based actions, render room state as authoritative, or conclude that the query returned no rows before the `init` snapshot.
9899

@@ -105,9 +106,7 @@ const watcher = db.collection("rooms")
105106
.where({ roomId })
106107
.watch({
107108
onChange(snapshot) {
108-
const isInit = snapshot.docChanges?.some(
109-
change => change.dataType === 'init'
110-
);
109+
const isInit = snapshot.type === 'init';
111110

112111
syncRoomState(snapshot.docs);
113112

@@ -161,7 +160,7 @@ function ChatRoom({ roomId }) {
161160
onChange(snapshot) {
162161
handleNewMessages(snapshot);
163162

164-
if (!initialReady && snapshot.docChanges?.some(change => change.dataType === 'init')) {
163+
if (!initialReady && snapshot.type === 'init') {
165164
initialReady = true;
166165
setLoading(false);
167166
}

config/source/skills/no-sql-web-sdk/SKILL.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Keep local `references/...` paths for files that ship with the current skill dir
4646
- Querying before the user is signed in when the collection rules require identity.
4747
- Using `wx.cloud.database()` or Node SDK patterns in browser code.
4848
- Initializing CloudBase lazily with dynamic imports instead of a shared synchronous app instance.
49-
- For realtime UI, assuming the listener is ready immediately after calling `watch()`. Treat the first `onChange` snapshot whose `docChanges` contain `dataType: 'init'` as the initial data ready signal before rendering room state, enabling actions, or concluding that the query returned no rows.
49+
- For realtime UI, assuming the listener is ready immediately after calling `watch()`. Treat the first `onChange` snapshot whose `snapshot.type === 'init'` as the canonical initial data ready signal before rendering room state, enabling actions, or concluding that the query returned no rows.
5050
- Treating security rules as result filters rather than request validators.
5151
- For CMS-style collections that need **app-level admin users** to edit/delete all records while editors can only edit/delete their own records, do not oversimplify the rule to `READONLY`. A validated pattern is a `CUSTOM` rule that reads role from `user_roles` by `auth.uid` and combines it with `doc.authorId == auth.uid`, while frontend writes can stay on `.doc(id).update()` / `.doc(id).remove()`.
5252
- Forgetting pagination or indexes for larger collections.
@@ -122,7 +122,8 @@ Important rules:
122122

123123
5. **Handle realtime initialization explicitly**
124124
- `.watch()` becomes usable only after the first `onChange` snapshot arrives.
125-
- Use the snapshot whose `docChanges` include `dataType: 'init'` as the canonical "initial data is ready" event.
125+
- Use the snapshot whose `type` is `init` as the canonical "initial data is ready" event.
126+
- If you also inspect `docChanges`, the initial payload may include `dataType: 'init'`, but do not treat the query as ready before that first init snapshot arrives.
126127
- Until that event arrives, keep loading state explicit and avoid enabling turn-based actions that depend on the queried documents.
127128

128129
## Quick examples

config/source/skills/no-sql-web-sdk/realtime.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ Create a real-time data listener that returns a `watcher` object.
9292

9393
Calling `.watch()` only starts the listener setup. Do not assume the queried data is ready immediately after `watch()` returns.
9494

95-
- Treat the first `onChange` snapshot whose `docChanges` contain `dataType: 'init'` as the canonical "initial data is ready" signal.
95+
- Treat the first `onChange` snapshot whose `type` is `init` as the canonical "initial data is ready" signal.
96+
- The initial payload may also include `docChanges` items with `dataType: 'init'`, but the listener is not ready until that first init snapshot arrives.
9697
- Until that `init` snapshot arrives, keep loading state explicit.
9798
- Do not enable turn-based actions, render room state as authoritative, or conclude that the query returned no rows before the `init` snapshot.
9899

@@ -105,9 +106,7 @@ const watcher = db.collection("rooms")
105106
.where({ roomId })
106107
.watch({
107108
onChange(snapshot) {
108-
const isInit = snapshot.docChanges?.some(
109-
change => change.dataType === 'init'
110-
);
109+
const isInit = snapshot.type === 'init';
111110

112111
syncRoomState(snapshot.docs);
113112

@@ -161,7 +160,7 @@ function ChatRoom({ roomId }) {
161160
onChange(snapshot) {
162161
handleNewMessages(snapshot);
163162

164-
if (!initialReady && snapshot.docChanges?.some(change => change.dataType === 'init')) {
163+
if (!initialReady && snapshot.type === 'init') {
165164
initialReady = true;
166165
setLoading(false);
167166
}

0 commit comments

Comments
 (0)