

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Utilizzo delle operazioni batch di DynamoDB in AWS AppSync
<a name="tutorial-dynamodb-batch-js"></a>

AWS AppSync supporta l'utilizzo di operazioni batch di Amazon DynamoDB su una o più tabelle in una singola regione. Le operazioni supportate sono `BatchGetItem`, `BatchPutItem` e `BatchDeleteItem`. Utilizzando queste funzionalità in AWS AppSync, puoi eseguire attività come:
+ Passare un elenco di chiavi in una singola query e restituire i risultati da una tabella
+ Leggere i record da una o più tabelle in una singola query
+ Scrittura di record in blocco su una o più tabelle
+ Scrittura o eliminazione condizionale di record in più tabelle che potrebbero avere una relazione

Le operazioni batch AWS AppSync presentano due differenze fondamentali rispetto alle operazioni non in batch:
+ Il ruolo dell'origine dati deve disporre delle autorizzazioni per tutte le tabelle a cui accederà il resolver.
+ La specifica della tabella per un resolver fa parte dell'oggetto della richiesta.

## Batch a tabella singola
<a name="single-table-batch-js"></a>

**avvertimento**  
`BatchPutItem`e non `BatchDeleteItem` sono supportati se utilizzati per il rilevamento e la risoluzione dei conflitti. Queste impostazioni devono essere disabilitate per evitare possibili errori.

Per iniziare, creiamo una nuova API GraphQL. Nella AWS AppSync console, scegli **Create API**, **GraphQL APIs** e **Design da zero**. **Assegna un nome all'API`BatchTutorial API`, scegli **Avanti** e nel passaggio **Specificare le risorse GraphQL, scegli Crea risorse** **GraphQL in un secondo momento e fai clic** su Avanti.** Controlla i tuoi dati e crea l'API. Vai alla pagina **Schema** e incolla lo schema seguente, notando che per la query inseriremo un elenco di IDs:

```
type Post {
    id: ID!
    title: String
}

input PostInput {
    id: ID!
    title: String
}

type Query {
    batchGet(ids: [ID]): [Post]
}

type Mutation {
    batchAdd(posts: [PostInput]): [Post]
    batchDelete(ids: [ID]): [Post]
}
```

Salva lo schema e scegli **Crea risorse** nella parte superiore della pagina. Scegli **Usa il tipo esistente** e seleziona il `Post` tipo. Assegna un nome alla tua tabella`Posts`. **Assicurati che la **chiave primaria** sia impostata su`id`, deseleziona **Genera automaticamente GraphQL** (fornirai il tuo codice) e seleziona Crea.** Per iniziare, AWS AppSync crea una nuova tabella DynamoDB e un'origine dati connessa alla tabella con i ruoli appropriati. Tuttavia, ci sono ancora un paio di autorizzazioni da aggiungere al ruolo. Vai alla pagina **Fonti di dati** e scegli la nuova fonte di dati. In **Seleziona un ruolo esistente**, noterai che un ruolo è stato creato automaticamente per la tabella. Prendi nota del ruolo (dovrebbe assomigliare a qualcosa del genere`appsync-ds-ddb-aaabbbcccddd-Posts`) e poi vai alla console IAM ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)). Nella console IAM, scegli **Ruoli**, quindi scegli il tuo ruolo dalla tabella. Nel tuo ruolo, in **Politiche di autorizzazione**, fai clic sul pulsante `+` "" accanto alla politica (dovrebbe avere un nome simile al nome del ruolo). Scegli **Modifica** nella parte superiore del pannello comprimibile quando viene visualizzata la politica. Devi aggiungere autorizzazioni batch alla tua politica, in particolare `dynamodb:BatchGetItem` e. `dynamodb:BatchWriteItem` Assomiglierà a questo:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:UpdateItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:BatchGetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-east-1:111122223333:table/locationReadings",
                "arn:aws:dynamodb:us-east-1:111122223333:table/locationReadings/*",
                "arn:aws:dynamodb:us-east-1:111122223333:table/temperatureReadings",
                "arn:aws:dynamodb:us-east-1:111122223333:table/temperatureReadings/*"
            ]
        }
    ]
}
```

------

Scegli **Avanti**, quindi **Salva modifiche**. La tua politica dovrebbe ora consentire l'elaborazione in batch.

Tornando alla AWS AppSync console, vai alla pagina **Schema** e seleziona **Allega** accanto al `Mutation.batchAdd` campo. Crea il tuo resolver usando la `Posts` tabella come fonte di dati. Nell'editor di codice, sostituisci i gestori con lo snippet riportato di seguito. Questo frammento prende automaticamente ogni elemento del `input PostInput` tipo GraphQL e crea una mappa, necessaria per l'operazione: `BatchPutItem`

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchPutItem",
    tables: {
      Posts: ctx.args.posts.map((post) => util.dynamodb.toMapValues(post)),
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

Vai alla pagina **Query** della AWS AppSync console ed esegui la seguente mutazione: `batchAdd`

```
mutation add {
    batchAdd(posts:[{
            id: 1 title: "Running in the Park"},{
            id: 2 title: "Playing fetch"
        }]){
            id
            title
    }
}
```

Dovresti vedere i risultati stampati sullo schermo; questo può essere convalidato esaminando la console DynamoDB per cercare i valori scritti nella tabella. `Posts`

Quindi, ripeti il processo di collegamento di un resolver ma per il `Query.batchGet` campo utilizzando la `Posts` tabella come fonte di dati. Sostituisci i gestori con il codice seguente. Questo prende automaticamente ogni voce nel tipo `ids:[]` di GraphQL e crea una mappa, che risulta necessaria per l'operazione `BatchGetItem`:

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchGetItem",
    tables: {
      Posts: {
        keys: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
        consistentRead: true,
      },
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

Ora torna alla pagina **Query della AWS AppSync console ed esegui la seguente query**: `batchGet`

```
query get {
    batchGet(ids:[1,2,3]){
        id
        title
    }
}
```

Questo dovrebbe restituire i risultati per i due valori `id` aggiunti in precedenza. Nota che è stato restituito un `null` valore per il `id` con un valore di`3`. Questo perché non c'era ancora nessun record nella `Posts` tabella con quel valore. Tieni inoltre presente che AWS AppSync restituisce i risultati nello stesso ordine delle chiavi passate alla query, che è una funzionalità aggiuntiva che viene AWS AppSync eseguita per conto dell'utente. Quindi, se passi a`batchGet(ids:[1,3,2])`, vedrai che l'ordine è cambiato. È inoltre possibile sapere quale `id` ha restituito un valore `null`.

Infine, collega un altro resolver al `Mutation.batchDelete` campo usando la `Posts` tabella come fonte di dati. Sostituisci i gestori con il codice seguente. Questo prende automaticamente ogni voce nel tipo `ids:[]` di GraphQL e crea una mappa, che risulta necessaria per l'operazione `BatchGetItem`:

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchDeleteItem",
    tables: {
      Posts: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

Ora torna alla pagina **Queries** della AWS AppSync console ed esegui la seguente mutazione: `batchDelete`

```
mutation delete {
    batchDelete(ids:[1,2]){ id }
}
```

I record con `id` `1` e `2` dovrebbero essere eliminati. Se si esegue nuovamente la query `batchGet()` da una versione precedente, questi devono restituire `null`.

## Batch multitavola
<a name="multi-table-batch-js"></a>

**avvertimento**  
`BatchPutItem`e non `BatchDeleteItem` sono supportati se utilizzati per il rilevamento e la risoluzione dei conflitti. Queste impostazioni devono essere disabilitate per evitare possibili errori.

AWS AppSync consente inoltre di eseguire operazioni in batch su più tabelle. L'applicazione seguente è più complessa da costruire. Immagina di costruire un'app per la salute degli animali domestici in cui i sensori segnalano la posizione e la temperatura corporea dell'animale. I sensori sono dotati di batteria e tentano di connettersi alla rete a distanza di pochi minuti. Quando un sensore stabilisce una connessione, invia le sue letture alla nostra API. AWS AppSync I trigger quindi analizzano i dati in modo da presentare un pannello di controllo al proprietario dell'animale domestico, focalizzando l'attenzione sulla rappresentazione delle interazioni tra il sensore e l'archivio di dati di back-end.

Nella AWS AppSync console, scegli **Create API**, **GraphQL APIs** e **Design da zero**. **Assegna un nome all'API`MultiBatchTutorial API`, scegli **Avanti** e nel passaggio **Specificare le risorse GraphQL, scegli Crea risorse** **GraphQL in un secondo momento e fai clic** su Avanti.** Controlla i tuoi dati e crea l'API. Vai alla pagina **Schema** e incolla e salva lo schema seguente:

```
type Mutation {
    # Register a batch of readings
    recordReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult
    # Delete a batch of readings
    deleteReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult
}

type Query {
    # Retrieve all possible readings recorded by a sensor at a specific time
    getReadings(sensorId: ID!, timestamp: String!): [SensorReading]
}

type RecordResult {
    temperatureReadings: [TemperatureReading]
    locationReadings: [LocationReading]
}

interface SensorReading {
    sensorId: ID!
    timestamp: String!
}

# Sensor reading representing the sensor temperature (in Fahrenheit)
type TemperatureReading implements SensorReading {
    sensorId: ID!
    timestamp: String!
    value: Float
}

# Sensor reading representing the sensor location (lat,long)
type LocationReading implements SensorReading {
    sensorId: ID!
    timestamp: String!
    lat: Float
    long: Float
}

input TemperatureReadingInput {
    sensorId: ID!
    timestamp: String
    value: Float
}

input LocationReadingInput {
    sensorId: ID!
    timestamp: String
    lat: Float
    long: Float
}
```

Dobbiamo creare due tabelle DynamoDB:
+ `locationReadings`memorizzerà le letture sulla posizione del sensore.
+ `temperatureReadings`memorizzerà le letture della temperatura del sensore.

Entrambe le tabelle condivideranno la stessa struttura di chiave primaria: `sensorId (String)` come chiave di partizione e `timestamp (String)` come chiave di ordinamento.

Scegli **Crea risorse** nella parte superiore della pagina. Scegli **Usa il tipo esistente** e seleziona il `locationReadings` tipo. Assegna un nome alla tua tabella`locationReadings`. Assicurati che la **chiave primaria** sia impostata su `sensorId` e la chiave di ordinamento su`timestamp`. **Deseleziona **Genera automaticamente GraphQL** (dovrai fornire il tuo codice) e seleziona Crea.** Ripeti questo processo per `temperatureReadings` utilizzare `temperatureReadings` come nome del tipo e della tabella. Utilizzate gli stessi tasti di cui sopra.

Le nuove tabelle conterranno ruoli generati automaticamente. Ci sono ancora un paio di autorizzazioni da aggiungere a questi ruoli. Vai alla pagina **Fonti di dati** e scegli`locationReadings`. In **Seleziona un ruolo esistente**, puoi vedere il ruolo. Prendi nota del ruolo (dovrebbe assomigliare a qualcosa del genere`appsync-ds-ddb-aaabbbcccddd-locationReadings`) e poi vai alla console IAM ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)). Nella console IAM, scegli **Ruoli**, quindi scegli il tuo ruolo dalla tabella. Nel tuo ruolo, in **Politiche di autorizzazione**, fai clic sul pulsante `+` "" accanto alla politica (dovrebbe avere un nome simile al nome del ruolo). Scegli **Modifica** nella parte superiore del pannello comprimibile quando viene visualizzata la politica. È necessario aggiungere autorizzazioni a questa politica. Avrà un aspetto simile a questo:

Scegli **Avanti**, quindi **Salva modifiche**. Ripeti questo processo per l'origine `temperatureReadings` dati utilizzando lo stesso frammento di policy riportato sopra.

### BatchPutItem - Registrazione delle letture del sensore
<a name="batchputitem-recording-sensor-readings-js"></a>

I sensori devono essere in grado di inviare le loro letture una volta stabilita la connessione a Internet. Il campo `Mutation.recordReadings` di GraphQL è l'API che si userà per farlo. Dovremo aggiungere un resolver a questo campo.

Nella pagina **Schema** della AWS AppSync console, seleziona **Allega** accanto al `Mutation.recordReadings` campo. Nella schermata successiva, crea il tuo resolver usando la `locationReadings` tabella come fonte di dati.

Dopo aver creato il resolver, sostituisci i gestori con il seguente codice nell'editor. Questa `BatchPutItem` operazione ci consente di specificare più tabelle: 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const { locReadings, tempReadings } = ctx.args
	const locationReadings = locReadings.map((loc) => util.dynamodb.toMapValues(loc))
	const temperatureReadings = tempReadings.map((tmp) => util.dynamodb.toMapValues(tmp))

	return {
		operation: 'BatchPutItem',
		tables: {
			locationReadings,
			temperatureReadings,
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	return ctx.result.data
}
```

Con le operazioni in batch, possono essere presenti entrambi gli errori e i risultati restituiti dalla chiamata. In questo caso, è possibile eseguire liberamente ulteriori operazioni di gestione degli errori.

**Nota**  
L'uso di `utils.appendError()` è simile a`util.error()`, con la principale distinzione che non interrompe la valutazione del gestore della richiesta o della risposta. Segnala invece che c'è stato un errore nel campo ma consente di valutare il gestore e di conseguenza di restituire i dati al chiamante. Si consiglia di utilizzarlo `utils.appendError()` quando l'applicazione deve restituire risultati parziali.

Salva il resolver e vai alla pagina **Query** nella console. AWS AppSync Ora possiamo inviare alcune letture dei sensori.

Eseguire la mutazione seguente:

```
mutation sendReadings {
  recordReadings(
    tempReadings: [
      {sensorId: 1, value: 85.5, timestamp: "2018-02-01T17:21:05.000+08:00"},
      {sensorId: 1, value: 85.7, timestamp: "2018-02-01T17:21:06.000+08:00"},
      {sensorId: 1, value: 85.8, timestamp: "2018-02-01T17:21:07.000+08:00"},
      {sensorId: 1, value: 84.2, timestamp: "2018-02-01T17:21:08.000+08:00"},
      {sensorId: 1, value: 81.5, timestamp: "2018-02-01T17:21:09.000+08:00"}
    ]
    locReadings: [
      {sensorId: 1, lat: 47.615063, long: -122.333551, timestamp: "2018-02-01T17:21:05.000+08:00"},
      {sensorId: 1, lat: 47.615163, long: -122.333552, timestamp: "2018-02-01T17:21:06.000+08:00"},
      {sensorId: 1, lat: 47.615263, long: -122.333553, timestamp: "2018-02-01T17:21:07.000+08:00"},
      {sensorId: 1, lat: 47.615363, long: -122.333554, timestamp: "2018-02-01T17:21:08.000+08:00"},
      {sensorId: 1, lat: 47.615463, long: -122.333555, timestamp: "2018-02-01T17:21:09.000+08:00"}
    ]) {
    locationReadings {
      sensorId
      timestamp
      lat
      long
    }
    temperatureReadings {
      sensorId
      timestamp
      value
    }
  }
}
```

Abbiamo inviato dieci letture dei sensori in un'unica mutazione con letture suddivise su due tabelle. Utilizza la console DynamoDB per verificare che i dati vengano visualizzati sia nelle tabelle che nelle tabelle. `locationReadings` `temperatureReadings`

### BatchDeleteItem - Eliminazione delle letture dei sensori
<a name="batchdeleteitem-deleting-sensor-readings-js"></a>

Allo stesso modo, avremmo anche bisogno di poter eliminare lotti di letture dei sensori. Utilizzare il campo `Mutation.deleteReadings` di GraphQL per questo scopo. Nella pagina **Schema** della AWS AppSync console, seleziona **Allega** accanto al `Mutation.deleteReadings` campo. Nella schermata successiva, crea il tuo resolver usando la `locationReadings` tabella come fonte di dati.

Dopo aver creato il resolver, sostituisci i gestori nell'editor di codice con lo snippet riportato di seguito. In questo resolver, utilizziamo un mappatore di funzioni di supporto che estrae il e il dagli input forniti. `sensorId` `timestamp` 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const { locReadings, tempReadings } = ctx.args
	const mapper = ({ sensorId, timestamp }) => util.dynamodb.toMapValues({ sensorId, timestamp })

	return {
		operation: 'BatchDeleteItem',
		tables: {
			locationReadings: locReadings.map(mapper),
			temperatureReadings: tempReadings.map(mapper),
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	return ctx.result.data
}
```

**Salva il resolver e vai alla pagina Query nella console.** AWS AppSync Ora, eliminiamo un paio di letture del sensore.

Eseguire la mutazione seguente:

```
mutation deleteReadings {
  # Let's delete the first two readings we recorded
  deleteReadings(
    tempReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]
    locReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]) {
    locationReadings {
      sensorId
      timestamp
      lat
      long
    }
    temperatureReadings {
      sensorId
      timestamp
      value
    }
  }
}
```

**Nota**  
A differenza dell'operazione `DeleteItem`, nella risposta non viene restituita la voce completamente eliminata. Viene restituita solo la chiave passata. Per ulteriori informazioni, consulta il [riferimento alla funzione BatchDeleteItem in JavaScript resolver per DynamoDB](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-batch-delete-item).

Verifica tramite la console DynamoDB che queste due letture siano state eliminate dalle tabelle and. `locationReadings` `temperatureReadings`

### BatchGetItem - Recupera le letture
<a name="batchgetitem-retrieve-readings-js"></a>

Un'altra operazione comune per la nostra app sarebbe quella di recuperare le letture di un sensore in un momento specifico. Allegare un resolver al campo `Query.getReadings` di GraphQL sullo schema. Nella pagina **Schema** della AWS AppSync console, seleziona **Allega** accanto al `Query.getReadings` campo. Nella schermata successiva, crea il tuo resolver usando la `locationReadings` tabella come fonte di dati.

Usiamo il codice seguente: 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const keys = [util.dynamodb.toMapValues(ctx.args)]
	const consistentRead = true
	return {
		operation: 'BatchGetItem',
		tables: {
			locationReadings: { keys, consistentRead },
			temperatureReadings: { keys, consistentRead },
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	const { locationReadings: locs, temperatureReadings: temps } = ctx.result.data

	return [
		...locs.map((l) => ({ ...l, __typename: 'LocationReading' })),
		...temps.map((t) => ({ ...t, __typename: 'TemperatureReading' })),
	]
}
```

Salva il resolver e vai alla pagina **Query** nella console. AWS AppSync Ora, recuperiamo le letture dei nostri sensori.

Eseguire la query seguente:

```
query getReadingsForSensorAndTime {
  # Let's retrieve the very first two readings
  getReadings(sensorId: 1, timestamp: "2018-02-01T17:21:06.000+08:00") {
    sensorId
    timestamp
    ...on TemperatureReading {
      value
    }
    ...on LocationReading {
      lat
      long
    }
  }
}
```

Abbiamo dimostrato con successo l'uso delle operazioni batch di DynamoDB utilizzando. AWS AppSync

## Gestione degli errori
<a name="error-handling-js"></a>

Nel AWS AppSync, le operazioni sulle sorgenti dati a volte possono restituire risultati parziali. Risultati parziali è il termine che si userà per indicare quando l'output di un'operazione comprende alcuni dati e un errore. Poiché la gestione degli errori è intrinsecamente specifica dell'applicazione, AWS AppSync offre l'opportunità di gestire gli errori nel gestore delle risposte. L'errore di chiamata del resolver, se presente, è disponibile nel contesto come `ctx.error`. Gli errori di chiamata comprendono sempre un messaggio e un tipo, accessibili come proprietà `ctx.error.message` e `ctx.error.type`. Nel gestore delle risposte, è possibile gestire i risultati parziali in tre modi:

1. Ingoia l'errore di invocazione semplicemente restituendo i dati.

1. Genera un errore (using`util.error(...)`) interrompendo la valutazione del gestore, che non restituirà alcun dato.

1. Aggiungi un errore (usando`util.appendError(...)`) e restituisci anche i dati.

Dimostriamo ciascuno dei tre punti precedenti con le operazioni batch di DynamoDB.

### Operazioni di batch di DynamoDB
<a name="dynamodb-batch-operations-js"></a>

Con le operazioni di batch di DynamoDB, è possibile che un batch sia completato parzialmente. Ovvero, è possibile che alcune delle chiavi o voci richieste non vengano elaborate. Se non AWS AppSync è in grado di completare un batch, nel contesto verranno impostati gli elementi non elaborati e un errore di invocazione.

La gestione degli errori verrà realizzata tramite la configurazione del campo `Query.getReadings` dall'operazione `BatchGetItem` dalla sezione precedente di questo tutorial. In questo momento, è opportuno supporre che durante l'esecuzione del campo `Query.getReadings`, la tabella `temperatureReadings` DynamoDB esegua un throughput assegnato. DynamoDB ha generato `ProvisionedThroughputExceededException` un durante il secondo tentativo AWS AppSync per elaborare gli elementi rimanenti del batch.

Il seguente codice JSON rappresenta il contesto serializzato dopo la chiamata in batch di DynamoDB ma prima della chiamata del gestore delle risposte:

```
{
  "arguments": {
    "sensorId": "1",
    "timestamp": "2018-02-01T17:21:05.000+08:00"
  },
  "source": null,
  "result": {
    "data": {
      "temperatureReadings": [
        null
      ],
      "locationReadings": [
        {
          "lat": 47.615063,
          "long": -122.333551,
          "sensorId": "1",
          "timestamp": "2018-02-01T17:21:05.000+08:00"
        }
      ]
    },
    "unprocessedKeys": {
      "temperatureReadings": [
        {
          "sensorId": "1",
          "timestamp": "2018-02-01T17:21:05.000+08:00"
        }
      ],
      "locationReadings": []
    }
  },
  "error": {
    "type": "DynamoDB:ProvisionedThroughputExceededException",
    "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
  },
  "outErrors": []
}
```

Alcune cose da tenere presente in questo contesto:
+ L'errore di invocazione è stato impostato nel contesto in `ctx.error` by AWS AppSync e il tipo di errore è stato impostato su. `DynamoDB:ProvisionedThroughputExceededException`
+ I risultati vengono mappati per tabella sotto `ctx.result.data` anche se è presente un errore.
+ Le chiavi che non sono state elaborate sono disponibili all'indirizzo. `ctx.result.data.unprocessedKeys` In questo caso, non AWS AppSync è stato possibile recuperare l'elemento con la chiave (SensorID:1, timestamp:2018-02-01T 17:21:05.000 \$1 08:00) a causa dell'insufficiente velocità di trasmissione della tabella.

**Nota**  
Per `BatchPutItem`, è `ctx.result.data.unprocessedItems`. Per `BatchDeleteItem`, è `ctx.result.data.unprocessedKeys`.

È possibile gestire l'errore in tre modi diversi.

#### 1. Assumere l'errore di chiamata
<a name="swallowing-the-invocation-error-js"></a>

Restituire i dati senza gestire l'errore di chiamata assume efficacemente l'errore. In questo modo, il risultato per il campo di GraphQL è sempre positivo.

Il codice che scriviamo è familiare e si concentra solo sui dati dei risultati.

**Gestore di risposte**

```
export function response(ctx) {
  return ctx.result.data
}
```

**Risposta GraphQL**

```
{
  "data": {
    "getReadings": [
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "lat": 47.615063,
        "long": -122.333551
      },
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "value": 85.5
      }
    ]
  }
}
```

Non verrà aggiunto nessun errore alla risposta di errore poiché sono stati eseguiti solo i dati.

#### 2. Generazione di un errore per interrompere l'esecuzione del gestore di risposte
<a name="raising-an-error-to-abort-the-response-execution-js"></a>

Quando gli errori parziali devono essere trattati come errori completi dal punto di vista del client, è possibile interrompere l'esecuzione del gestore di risposte per impedire la restituzione dei dati. Il metodo di utilità `util.error(...)` raggiunge esattamente questo comportamento.

**Codice del gestore di risposte**

```
export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type, null, ctx.result.data.unprocessedKeys);
  }
  return ctx.result.data;
}
```

**Risposta GraphQL**

```
{
  "data": {
    "getReadings": null
  },
  "errors": [
    {
      "path": [
        "getReadings"
      ],
      "data": null,
      "errorType": "DynamoDB:ProvisionedThroughputExceededException",
      "errorInfo": {
        "temperatureReadings": [
          {
            "sensorId": "1",
            "timestamp": "2018-02-01T17:21:05.000+08:00"
          }
        ],
        "locationReadings": []
      },
      "locations": [
        {
          "line": 58,
          "column": 3
        }
      ],
      "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
    }
  ]
}
```

Sebbene alcuni risultati possano essere stati restituiti dall'operazione in batch di DynamoDB, si è scelto di generare un errore in modo tale che il campo `getReadings` di GraphQL sia nullo e l'errore venga aggiunto al blocco di *errori* della risposta GraphQL.

#### 3. Aggiunta di un errore per restituire sia i dati sia gli errori
<a name="appending-an-error-to-return-both-data-and-errors-js"></a>

In alcuni casi, per fornire una migliore esperienza utente, le applicazioni possono restituire risultati parziali e notificare ai client le voci non elaborate. I client possono decidere di implementare un nuovo tentativo oppure di rimandare l'errore all'utente finale. `util.appendError(...)`È il metodo di utilità che abilita questo comportamento consentendo al progettista dell'applicazione di aggiungere errori al contesto senza interferire con la valutazione del gestore della risposta. Dopo aver valutato il gestore della risposta, AWS AppSync elaborerà eventuali errori di contesto aggiungendoli al blocco errors della risposta GraphQL.

**Codice del gestore di risposte**

```
export function response(ctx) {
  if (ctx.error) {
    util.appendError(ctx.error.message, ctx.error.type, null, ctx.result.data.unprocessedKeys);
  }
  return ctx.result.data;
}
```

Abbiamo inoltrato sia l'errore di invocazione che l'`unprocessedKeys`elemento all'interno del blocco errors della risposta GraphQL. Il `getReadings` campo restituisce anche dati parziali dalla `locationReadings` tabella, come puoi vedere nella risposta seguente.

**Risposta GraphQL**

```
{
  "data": {
    "getReadings": [
      null,
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "value": 85.5
      }
    ]
  },
  "errors": [
    {
      "path": [
        "getReadings"
      ],
      "data": null,
      "errorType": "DynamoDB:ProvisionedThroughputExceededException",
      "errorInfo": {
        "temperatureReadings": [
          {
            "sensorId": "1",
            "timestamp": "2018-02-01T17:21:05.000+08:00"
          }
        ],
        "locationReadings": []
      },
      "locations": [
        {
          "line": 58,
          "column": 3
        }
      ],
      "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
    }
  ]
}
```