Apollo mutate 为单个突变调用更新四次
Posted
技术标签:
【中文标题】Apollo mutate 为单个突变调用更新四次【英文标题】:Apollo mutate calling update four times for a single mutation 【发布时间】:2018-08-13 13:48:56 【问题描述】:每次我在我的应用程序中添加一个新项目时,突变都会调用update()
四次次,出于某种原因。前两个是乐观数据,第二批,一个是乐观数据,一个是来自网络的真实数据。我无法理解这一点。正在创建的新项目在页面上显示两次。
这是我的突变:
mutation CreateTrack($name: String!, $trackNum: Int, $s3Key: String!)
createTrack(name: $name, trackNum: $trackNum, s3Key: $s3Key)
trackId
name
createdAt
duration
trackNum
s3Key
isProcessing
didProcessingFail
这是变异代码:
createTrack( name, s3Key )
const newTrack =
name,
s3Key,
;
this.$apollo
.mutate(
mutation: createTrackMutation,
variables: newTrack,
update: (store, data: createTrack ) =>
console.log('this is dumb', JSON.stringify(createTrack, null, 2));
const variables =
limit: this.pageSize,
order: this.order === 'ascending' ? 'asc' : 'desc',
sortBy: this.sortBy,
;
const data = store.readQuery(
query: listTracksQuery,
variables,
);
data.listTracks.items.push(createTrack);
store.writeQuery(
query: listTracksQuery,
variables,
data,
);
,
optimisticResponse:
__typename: 'Mutation',
createTrack:
__typename: 'Track',
...newTrack,
trackId: '??',
createdAt: new Date().toISOString(),
isProcessing: true,
didProcessingFail: false,
duration: null,
trackNum: 999,
,
,
)
.then(data =>
console.log('done!', data);
)
.catch(err =>
console.log('error', err);
);
,
最后,这里是调用 mutate 一次的控制台日志:
this is dumb
"__typename": "Track",
"name": "small2.wav",
"s3Key": "staging/audio/10e3e675-e7a6-41dc-a8fb-686ad683e40e.wav",
"trackId": "??",
"createdAt": "2018-03-05T03:30:18.246Z",
"isProcessing": true,
"didProcessingFail": false,
"duration": null,
"trackNum": 999
this is dumb
"__typename": "Track",
"name": "small2.wav",
"s3Key": "staging/audio/10e3e675-e7a6-41dc-a8fb-686ad683e40e.wav",
"trackId": "??",
"createdAt": "2018-03-05T03:30:18.246Z",
"isProcessing": true,
"didProcessingFail": false,
"duration": null,
"trackNum": 999
done! data: ...
this is dumb
"__typename": "Track",
"name": "small2.wav",
"s3Key": "staging/audio/10e3e675-e7a6-41dc-a8fb-686ad683e40e.wav",
"trackId": "??",
"createdAt": "2018-03-05T03:30:18.246Z",
"isProcessing": true,
"didProcessingFail": false,
"duration": null,
"trackNum": 999
this is dumb
"trackId": "2b3de8ac-d145-4da6-b522-27e5413d43e1",
"name": "small2.wav",
"createdAt": "2018-03-05T03:30:18.627Z",
"duration": null,
"trackNum": 999,
"s3Key": "staging/audio/10e3e675-e7a6-41dc-a8fb-686ad683e40e.wav",
"isProcessing": true,
"didProcessingFail": null,
"__typename": "Track"
我在这里做错了什么?
【问题讨论】:
我认为这与我在此处描述的问题相同:***.com/a/48989517/2805067 我认为 PR(在此处的评论中)修复了一个未调用update
的相关问题。所以现在你看到它是从 aws-appsync
内部创建的第二个突变中调用的(第 3 次和第 4 次)。
所以 PR 解决了一个问题,但又创造了另一个问题,也许吧?该项目在网页上显示了两次,这不应该发生。
我已经编辑了我的帖子,以澄清数据在页面上的显示方式存在实际问题。所以这不仅仅是内部问题。
我不认为 PR 创造了一个新问题。这只是部分修复。
【参考方案1】:
我刚刚与处理此代码的工程师聊了聊。您所看到的是 AWS AppSync 开发工具包流程在幕后使用的簿记流程,以确保数据完整性。 不是实际上对您的 API 运行了 4 次突变。
当 AppSync 客户端获得乐观响应时,更新函数会运行两次 - 一次用于本地响应,一次用于网络响应。这是标准的 Apollo 行为。 AppSync 客户端在幕后所做的是第一个乐观响应,我们将其视为网络响应并将数据存储在持久存储介质中(Web 本地存储,React Native 异步存储)以允许乐观 UI处于离线状态时。这本质上是一个“发件箱”,数据在离线时首先被写入(当前实现使用 Redux Offline),如果您使用 disableOffline:true
禁用离线,您将不再看到此行为。
当您重新联机时,同步过程将被执行,您会看到客户端将其发送到服务器的另一条变异消息(实际上是原始变异)以及相应的响应。
请注意,如果您在客户端的乐观响应中创建唯一 ID,并且还在服务器上创建唯一 ID,例如使用 $util.autoId()
,那么您可能会有重复记录,因为我们不会覆盖您的任何本地数据'已经明确分配了一个 ID。如果您愿意,您可以在 AppSync 的 DynamoDB 解析器中使用 Offline-enabled put item 和 Offline-enabled response 模板来使任何本地创建的 ID 失效,这些模板使用名为 relayState
的临时密钥(您需要将其添加为您正在创建的类型的字段),您可以使用它来跟踪本地 ID 并将其与在服务器上创建的 ID 匹配。
我们将在未来对该簿记流程进行更多补充,欢迎在我们的 GitHub 问题回购中提出建议:https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues
【讨论】:
感谢理查德的解释。我正在努力解决这个问题,并保证离线突变持久性。我是否正确理解 AwsApolloClient 会执行此操作并接管 apollo-cache-persist 之类的工作? @CarlLippert 是的,这是正确的,AWS AppSync 客户端自动将缓存持久化到磁盘,处理离线突变、冲突解决、同步等。您可以将其视为与基础 Apollo 客户端。以上是关于Apollo mutate 为单个突变调用更新四次的主要内容,如果未能解决你的问题,请参考以下文章
Apollo GraphQL Mutation 为列表中的每个项目单独加载
Vue-Apollo GraphQL Mutation 未正确调用