1

アプリに新しいアイテムを追加するたびに、何らかの理由でミューテーションがupdate() 4回呼び出されます。最初の 2 つは楽観的なデータであり、2 番目のバッチでは、1 つは楽観的で、もう 1 つはネットワークからの実際のデータです。私はこれを理解することはできません。作成中の新しいアイテムがページに 2 回表示されます。

これは私の突然変異です:

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 onceを呼び出したコンソール ログを次に示します。

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"
}

ここで何が間違っていますか?

4

1 に答える 1

4

このコードに取り組んでいるエンジニアとチャットしました。表示されているのは、AWS AppSync SDK プロセスが内部で使用してデータの整合性を確保する予約プロセスです。実際には、API に対してミューテーションを 4 回実行しているわけではありません。

AppSync クライアントが楽観的な応答を取得すると、更新機能が 2 回実行されます。1 回はローカル応答用、もう 1 回はネットワーク応答用です。これは標準的な Apollo の動作です。AppSync クライアントが内部で行うことは、最初の楽観的な応答です。それをネットワーク応答であるかのように扱い、データを永続的なストレージ メディア (Web の場合はローカル ストレージ、React Native の場合は非同期ストレージ) に保存して、楽観的な UI を許可します。オフライン状態のとき。これは基本的に、オフライン時にデータが最初に書き込まれる「送信ボックス」であり (現在、実装では Redux Offline が使用されています)、オフラインを無効にすると、disableOffline:trueこの動作は見られなくなります。

オンラインに戻ると、同期プロセスが実行され、これをサーバーに送信するクライアントの別のミューテーション メッセージ (実際には元のミューテーション) と適切な応答が表示されます。

クライアントの楽観的応答で一意の ID を作成し、サーバーでも一意の ID を作成している場合、たとえば を使用して、$util.autoId()明示的に ID を割り当てたローカル データを上書きしないため、レコードが重複する可能性があることに注意してください。必要に応じて、AppSync 用の DynamoDB リゾルバーでオフライン対応のput アイテムオフライン対応の応答テンプレートを使用して、ローカルで作成された ID を無効にすることができrelayStateます。これを使用して、ローカル ID を追跡し、それをサーバーで作成された ID と照合できます。

今後、この予約プロセスにさらに追加を行う予定であり、GitHub の問題リポジトリ ( https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues ) で提案を歓迎します。

于 2018-03-06T23:21:37.633 に答える