Apollo变异呼叫针对单个变异进行四次更新 [英] Apollo mutate calling update four times for a single mutation

查看:143
本文介绍了Apollo变异呼叫针对单个变异进行四次更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每次我在应用程序中添加新项目时,由于某种原因,该变体调用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"
}

我在做什么错了?

解决方案

我刚刚与处理此代码的工程师进行了交谈.您所看到的是AWS AppSync SDK流程在后台使用的保管流程,以确保数据完整性.实际上,不是对您的API进行了4次变异.

当AppSync客户端获得乐观响应时,更新功能将运行两次-一次用于本地响应,一次用于网络响应.这是标准的阿波罗行为. AppSync客户端在幕后所做的工作是在第一个乐观响应上,我们将其视为网络响应,并将数据存储在持久性存储介质(用于Web的本地存储,用于React Native的Async存储)中,以允许乐观UI处于离线状态时.本质上,这是一个发件箱",数据在脱机时首先被写入(当前实现使用Redux脱机),并且如果您使用disableOffline:true禁用脱机,您将不再看到此行为.

当您重新联机时,同步过程将被执行,并且您会看到客户端的另一个变异消息(实际上是原始变异)将其发送到服务器以及相应的响应.

请注意,如果您要在客户端的乐观响应中创建唯一ID,并在服务器上也创建唯一ID(例如,使用$util.autoId()),则可能会有重复的记录,因为我们不会覆盖任何本地数据, ve明确分配了一个ID.如果需要,可以使用DynamoDB解析器for AppSync中的已启用离线的放置项已启用离线的响应模板来使任何本地创建的ID无效,该模板使用名为relayState的临时密钥(您需要将其添加为要创建的类型的字段),可用于跟踪本地ID并将其与在服务器上创建的ID匹配. >

将来,我们将在此bookeeper流程中添加更多内容,并欢迎我们在GitHub问题回购中提供建议:

What am I doing wrong here?

I just chatted through this with the Engineer that worked on this code. What you're seeing is the bookeeping process that the AWS AppSync SDK process uses under the covers to ensure data integrity. It is NOT actually running a mutation 4 times against your API.

When the AppSync client gets an optimistic response the update function runs twice - once for the local response and once for the network response. This is standard Apollo behavior. What the AppSync client does under the covers is on the first optimistic response, we treat it as if it were the network response and store the data in a persistent storage medium (local storage for web, Async Storage for React Native) to allow optimistic UI when in an offline state. This is essentially an "outbox" that the data first gets written to when offline (currently the implementation uses Redux Offline) and if you disable offline with disableOffline:true you will no longer see this behavior.

When you come back online, the synchronization process gets executed and you see another mutation message (which is actually the original mutation) of the client sending this to the server and the appropriate response.

Note that if you are creating unique IDs in your optimistic response on the client AND also creating unique IDs on the server, for instance using the $util.autoId() then you could have duplicate records as we will not overwrite any local data you've explicitly assigned an ID. You can do invalidation of any locally-created IDs if you wish by using the Offline-enabled put item and Offline-enabled response templates in the DynamoDB resolvers for AppSync which use an ephemeral key called relayState (that you'll need to add as a field for the type you're creating) that you can use to track the local ID and match it up with the ID that was created at the server.

There are more additions we're going to be making to this bookeeping process in the future and would welcome suggestions in our GitHub issues repo: https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues

这篇关于Apollo变异呼叫针对单个变异进行四次更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆