

La versión 2 de AWS SDK para JavaScript ha llegado al final del soporte. Se recomienda que migre a [AWS SDK para JavaScript v3](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/). Para ver detalles e información adicionales sobre cómo realizar la migración, consulte este [anuncio](https://aws.amazon.com/blogs//developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/).

# Llamadas asíncronas a servicios
<a name="calling-services-asynchronously"></a>

Todas las solicitudes que se realizan a través del SDK son asíncronas. Es importante recordarlo cuando se escriben scripts de navegador. La ejecución de JavaScript en un navegador web normalmente tiene un solo subproceso de ejecución. Después de realizar una llamada asíncrona a un servicio de AWS, el script de navegador continúa ejecutándose y, en el proceso, puede intentar ejecutar código que dependa de ese resultado asíncrono antes de volver.

La realización de llamadas asíncronas a un servicio de AWS incluye la administración de dichas llamadas de modo que su código no intente utilizar datos antes de que estos estén disponibles. En los temas de esta sección se explica la necesidad de administrar llamadas asíncronas y técnicas diferentes de detalles que puede utilizar para administrarlas.

**Topics**
+ [Administración de llamadas asíncronas](making-asynchronous-calls.md)
+ [Uso de una función de devolución de llamada anónima](using-a-callback-function.md)
+ [Uso de un objeto de un agente de escucha de eventos de objetos de solicitud](using-a-response-event-handler.md)
+ [Uso de async/await](using-async-await.md)
+ [Uso de promesas de JavaScript](using-promises.md)

# Administración de llamadas asíncronas
<a name="making-asynchronous-calls"></a>

Por ejemplo, la página de inicio de un sitio web de e-commerce permite iniciar sesión a los clientes que regresan. Parte del beneficio para los clientes que inician sesión es que, después de iniciar sesión, el sitio se personaliza a sí mismo para adaptarse a sus preferencias concretas. Para que esto suceda:

1. El cliente tiene que iniciar sesión y validarse con sus credenciales de inicio de sesión.

1. Las preferencias del cliente se solicitan a partir de una base de datos del cliente.

1. La base de datos proporciona las preferencias del cliente que se utilizan para personalizar el sitio antes de que se cargue la página.

Si dichas tareas se ejecutan de forma síncrona, cada una tiene que finalizar antes de que la siguiente pueda comenzar. La página web no puede acabar de cargarse hasta que no lleguen las preferencias del cliente desde la base de datos. Sin embargo, después de que la consulta de la base de datos se envíe al servidor, la recepción de los datos del cliente se puede retrasar o incluso generar errores debido a atascos en la red, un tráfico de base de datos excepcionalmente alto o una conexión de dispositivo móvil de mala calidad.

Para evitar que el sitio web se congele en estas condiciones, llame a la base de datos de forma asíncrona. Después de que se ejecute la llamada a la base de datos y se envíe su solicitud asíncrona, el código sigue ejecutándose según lo previsto. Si no administra correctamente la respuesta de una llamada asíncrona, el código puede intentar utilizar información que espera recibir de la base de datos cuando dichos datos todavía no están disponibles.

![\[Diferencia entre la ejecución síncrona y la ejecución asíncrona.\]](http://docs.aws.amazon.com/es_es/sdk-for-javascript/v2/developer-guide/images/async-vs-sync.png)


# Uso de una función de devolución de llamada anónima
<a name="using-a-callback-function"></a>

Cada método de objeto de servicio que crea un objeto `AWS.Request` puede aceptar una función de devolución de llamada anónima como último parámetro. La firma de dicha función de devolución de llamada es:

```
function(error, data) {
    // callback handling code
}
```

Esta función de devolución de llamada se ejecuta cuando se devuelve una respuesta correcta o datos de error. Si la llamada al método se realiza correctamente, el contenido de la respuesta está disponible en la función de devolución de llamada en el parámetro `data`. Si la llamada no se realiza correctamente, se proporcionan los detalles sobre el error en el parámetro `error`.

Normalmente el código contenido en la función de devolución de llamada realiza una prueba para detectar errores. Si el resultado de la prueba devuelve errores, los procesará. Si no se devuelve ningún error, el código recuperará los datos de la respuesta en el parámetro `data`. La forma básica de la función de devolución de llamada es similar a la de este ejemplo.

```
function(error, data) {
    if (error) {
        // error handling code
        console.log(error);
    } else {
        // data handling code
        console.log(data);
    }
}
```

En el ejemplo anterior, los detalles del error o de los datos devueltos se registran en la consola. A continuación se muestra un ejemplo que muestra una función de devolución de llamada transferida como parte de una llamada a un método en un objeto de servicio.

```
new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances(function(error, data) {
  if (error) {
    console.log(error); // an error occurred
  } else {
    console.log(data); // request succeeded
  }
});
```

## Acceso a los objetos de solicitud y respuesta
<a name="access-request-response"></a>

Dentro de la función de devolución de llamada, la palabra clave de JavaScript `this` se refiere al objeto `AWS.Response` subyacente para la mayoría de los servicios. En el ejemplo siguiente, la propiedad `httpResponse` de un objeto `AWS.Response` se utiliza dentro de una función de devolución de llamada para registrar los datos de respuesta sin procesar y los encabezados para ayudar con la depuración.

```
new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances(function(error, data) {
  if (error) {
    console.log(error); // an error occurred
    // Using this keyword to access AWS.Response object and properties
    console.log("Response data and headers: " + JSON.stringify(this.httpResponse));
  } else {
    console.log(data); // request succeeded
  }
});
```

Además, debido a que el objeto `AWS.Response` tiene una propiedad `Request` que contiene la `AWS.Request` que se ha enviado a través de la llamada al método original, también puede obtener acceso a los detalles de la solicitud que se realizó.

# Uso de un objeto de un agente de escucha de eventos de objetos de solicitud
<a name="using-a-response-event-handler"></a>

Si no crea ni transfiere una función de devolución de llamada anónima como parámetro cuando llama a un método de objeto de servicio, la llamada al método genera un objeto `AWS.Request` que debe enviarse manualmente usando su método `send`.

Para procesar la respuesta, debe crear un agente de escucha de eventos para que el objeto `AWS.Request` registre una función de devolución de llamada para la llamada al método. En el siguiente ejemplo se muestra cómo crear el objeto `AWS.Request` para llamar a un método de objeto de servicio y al agente de escucha de eventos para que la devolución sea correcta.

```
// create the AWS.Request object
var request = new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances();

// register a callback event handler
request.on('success', function(response) {
  // log the successful data response
  console.log(response.data); 
});

// send the request
request.send();
```

Una vez que se ha llamado al método `send` en el objeto `AWS.Request`, el controlador de eventos se ejecuta cuando el objeto de servicio recibe un objeto `AWS.Response`.

Para obtener más información acerca del objeto `AWS.Request`, consulte [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html) en la referencia de la API. Para obtener más información acerca del objeto `AWS.Response`, consulte [Uso del objeto de respuesta](the-response-object.md) o [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html) en la referencia de la API.

## Encadenar varias devoluciones de llamadas
<a name="response-chaining-callbacks"></a>

Puede registrar varias devoluciones de llamada en cualquier objeto de solicitud. Se pueden registrar varias devoluciones de llamada para diferentes eventos o para el mismo evento. También puede encadenar devoluciones de llamadas, tal y como se muestra en el siguiente ejemplo.

```
request.
  on('success', function(response) {
    console.log("Success!");
  }).
  on('error', function(response) {
    console.log("Error!");
  }).
  on('complete', function() {
    console.log("Always!");
  }).
  send();
```

## Eventos de finalización de objetos de solicitud
<a name="request-object-completion-events"></a>

El objeto `AWS.Request` plantea estos eventos de finalización en función de la respuesta de cada método de operación de servicio:
+ `success`
+ `error`
+ `complete`

Puede registrar una función de devolución de llamada en respuesta a cualquiera de estos eventos. Para obtener una lista completa de todos los eventos de objetos de solicitud, consulte [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html) en la referencia de la API.

### El evento success
<a name="request-success-event"></a>

El evento `success` se plantea cuando se recibe una respuesta de éxito desde el objeto de servicio. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('success', function(response) { 
  // event handler code
});
```

La respuesta proporciona una propiedad `data` que contiene los datos de respuesta serializada del servicio. Por ejemplo, la siguiente llamada al método `listBuckets` del objeto de servicio de Amazon S3

```
s3.listBuckets.on('success', function(response) {
  console.log(response.data);
}).send();
```

devuelve la respuesta y luego imprime el siguiente contenido de la propiedad `data` a la consola.

```
{ Owner: { ID: '...', DisplayName: '...' },
  Buckets: 
   [ { Name: 'someBucketName', CreationDate: someCreationDate },
     { Name: 'otherBucketName', CreationDate: otherCreationDate } ],
  RequestId: '...' }
```

### El evento error
<a name="request-error-event"></a>

El evento `error` se plantea cuando se recibe una respuesta de error desde el objeto de servicio. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('error', function(error, response) { 
  // event handling code
});
```

Cuando el evento `error` se produce, el valor de la propiedad `data` de la respuesta es `null` y la propiedad `error` contiene los datos del error. El objeto `error` asociado se transfiere como primer parámetro a la función de devolución de llamada registrada. Por ejemplo, el código siguiente:

```
s3.config.credentials.accessKeyId = 'invalid';
s3.listBuckets().on('error', function(error, response) {
  console.log(error);
}).send();
```

devuelve el error y luego imprime los datos de error siguientes a la consola.

```
{ code: 'Forbidden', message: null }
```

### El evento complete
<a name="request-complete-event"></a>

El evento `complete` se produce cuando una llamada al objeto de servicio ha terminado, independientemente de si la llamada se traduce en éxito o en error. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('complete', function(response) { 
  // event handler code
});
```

Utilice la devolución de llamada del evento `complete` para gestionar cualquier limpieza de solicitud que debe ejecutarse independientemente de si el resultado ha sido un éxito o un error. Si utiliza los datos de respuesta dentro de una devolución de llamada para el evento `complete`, en primer lugar, compruebe las propiedades `response.data` o `response.error` antes de intentar obtener acceso a una de ellas, tal y como se muestra en el siguiente ejemplo.

```
request.on('complete', function(response) {
  if (response.error) {
    // an error occurred, handle it
  } else {
    // we can use response.data here
  }
}).send();
```

## Eventos de HTTP de objetos de solicitud
<a name="request-object-http-events"></a>

El objeto `AWS.Request` plantea estos eventos HTTP en función de la respuesta de cada método de operación de servicio:
+ `httpHeaders`
+ `httpData`
+ `httpUploadProgress`
+ `httpDownloadProgress`
+ `httpError`
+ `httpDone`

Puede registrar una función de devolución de llamada en respuesta a cualquiera de estos eventos. Para obtener una lista completa de todos los eventos de objetos de solicitud, consulte [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html) en la referencia de la API.

### El evento httpHeaders
<a name="request-httpheaders-event"></a>

El evento `httpHeaders` se produce cuando el servidor remoto envía los encabezados. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('httpHeaders', function(statusCode, headers, response) {
  // event handling code
});
```

El parámetro `statusCode` para la función de devolución de llamada es el código de estado HTTP. El parámetro `headers` contiene los encabezados de la respuesta.

### El evento httpData
<a name="request-httpdata-event"></a>

El `httpData` evento se plantea para transmitir en streaming los paquetes de datos de respuesta desde el servicio. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('httpData', function(chunk, response) {
  // event handling code
});
```

Este evento se suele utilizar para recibir respuestas de gran tamaño en fragmentos cuando cargar toda la respuesta en la memoria no es práctico. Este evento tiene un parámetro `chunk` adicional que contiene una parte de los datos reales del servidor.

Si registra una devolución de llamada para el evento `httpData`, la propiedad `data` de la respuesta contiene toda la salida serializada de la solicitud. Debe eliminar el agente de escucha `httpData` predeterminado si no tiene la cantidad adicional de memoria y análisis adicional para los controladores integrados.

### Los eventos httpDownloadProgress y httpUploadProgress
<a name="request-httpupload-download-progress-event"></a>

El evento `httpUploadProgress` se produce cuando la solicitud HTTP ha cargado más datos. Igualmente, el evento `httpDownloadProgress` se produce cuando la solicitud HTTP ha descargado más datos. Aquí se muestra cómo registrar una función de devolución de llamada para estos eventos.

```
request.on('httpUploadProgress', function(progress, response) {
  // event handling code
})
.on('httpDownloadProgress', function(progress, response) {
  // event handling code
});
```

El parámetro `progress` para la función de devolución de llamada contiene un objeto con los bytes cargados y totales de la solicitud.

### El evento httpError
<a name="request-httperror-event"></a>

El evento `httpError` se produce cuando la solicitud HTTP genera un error. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('httpError', function(error, response) {
  // event handling code
});
```

El parámetro `error` para la función de devolución de llamada contiene el error que se generó.

### El evento httpDone
<a name="request-httpdone-event"></a>

El evento `httpDone` se produce cuando el servidor termina el envío de datos. Aquí se muestra cómo registrar una función de devolución de llamada para este evento.

```
request.on('httpDone', function(response) {
  // event handling code
});
```

# Uso de async/await
<a name="using-async-await"></a>

Puede utilizar el patrón `async/await` en sus llamadas al AWS SDK para JavaScript. La mayoría de las funciones que aceptan una devolución de llamada no devuelven una promesa. Como solo se utilizan funciones `await` que devuelven una promesa, para utilizar el patrón `async/await` hay que encadenar el método `.promise()` hasta el final de la llamada y eliminar la devolución de llamada.

En el siguiente ejemplo, se usa async/await para enumerar todas las tablas de Amazon DynamoDB en `us-west-2`.

```
var AWS = require("aws-sdk");
//Create an Amazon DynamoDB client service object.
dbClient = new AWS.DynamoDB({ region: "us-west-2" });
// Call DynamoDB to list existing tables
const run = async () => {
  try {
    const results = await dbClient.listTables({}).promise();
    console.log(results.TableNames.join("\n"));
  } catch (err) {
    console.error(err);
  }
};
run();
```

**nota**  
 No todos los navegadores admiten async/await. Consulte las [funciones asíncronas](https://caniuse.com/#feat=async-functions) para obtener una lista de navegadores compatibles con async/await. 

# Uso de promesas de JavaScript
<a name="using-promises"></a>

El método `AWS.Request.promise` proporciona una forma de llamar a una operación de servicio y administrar el flujo asíncrono en lugar de utilizar devoluciones de llamada. En Node.js y en los scripts de navegador, se devuelve un objeto `AWS.Request` cuando se llama a una operación de servicio sin una función de devolución de llamada. Puede llamar al método `send` de la solicitud para realizar la llamada de servicio.

Sin embargo, `AWS.Request.promise` comienza inmediatamente la llamada de servicio y devuelve una promesa que se cumple con la propiedad `data` de la respuesta o se rechaza con la propiedad `error` de la respuesta.

```
var request = new AWS.EC2({apiVersion: '2014-10-01'}).describeInstances();

// create the promise object
var promise = request.promise();

// handle promise's fulfilled/rejected states
promise.then(
  function(data) {
    /* process the data */
  },
  function(error) {
    /* handle the error */
  }
);
```

En el siguiente ejemplo se devuelve una promesa que se cumple con un objeto `data` o se rechaza con un objeto `error`. Con el uso de las promesas, una única devolución de llamada no es responsable de la detección de errores. En su lugar, se llama a la devolución de llamada correcta en función del éxito o el error de una solicitud.

```
var s3 = new AWS.S3({apiVersion: '2006-03-01', region: 'us-west-2'});
var params = {
  Bucket: 'bucket',
  Key: 'example2.txt',
  Body: 'Uploaded text using the promise-based method!'
};
var putObjectPromise = s3.putObject(params).promise();
putObjectPromise.then(function(data) {
  console.log('Success');
}).catch(function(err) {
  console.log(err);
});
```

## Coordinación de varias promesas
<a name="multiple-promises"></a>

En algunas situaciones, el código debe realizar varias llamadas asíncronas que requieren acción solo cuando todas han tenido una devolución correcta. Si administra estas llamadas a métodos asíncronas individuales con promesas, puede crear una promesa adicional que utilice el método `all`. Este método cumple esta promesa paraguas en el momento en que transfiere la matriz de promesas al método siempre y cuando dicha matriz de promesas se cumpla. Se transfiere a la función de devolución de llamada una matriz de los valores de las promesas que se transfieren al método `all`.

En el siguiente ejemplo, una función de Lambda tiene que realizar tres llamadas asíncronas a Amazon DynamoDB, pero solo puede completarse después de que las promesas para cada llamada se cumplan.

```
Promise.all([firstPromise, secondPromise, thirdPromise]).then(function(values) {
  
  console.log("Value 0 is " + values[0].toString);
  console.log("Value 1 is " + values[1].toString);
  console.log("Value 2 is " + values[2].toString);

  // return the result to the caller of the Lambda function
  callback(null, values);
});
```

## Compatibilidad del navegador y Node.js con las promesas
<a name="browser-node-promise-support"></a>

La compatibilidad con promesas de JavaScript (ECMAScript 2015) depende del motor y la versión de JavaScript en los que se ejecuta el código. Para ayudar a determinar la compatibilidad con las promesas de JavaScript en cada entorno donde el código necesita ejecutarse, consulte la [tabla de compatibilidad ECMAScript](https://compat-table.github.io/compat-table/es6/) en GitHub.

## Uso de otras implementaciones de promesas
<a name="using-other-promise-implementations"></a>

Además de la implementación de promesas nativa de ECMAScript 2015, también puede utilizar bibliotecas de promesas de terceros, como:
+ [bluebird](http://bluebirdjs.com)
+ [RSVP](https://github.com/tildeio/rsvp.js/)
+ [Q](https://github.com/kriskowal/q)

Estas bibliotecas de promesas opcionales pueden ser útiles si necesita que el código se ejecute en entornos que no admitan la implementación de promesas nativas en ECMAScript 5 y en ECMAScript de 2015.

Para utilizar una biblioteca de promesas de terceros, establezca una dependencia de promesas en el SDK llamando al método `setPromisesDependency` del objeto de configuración global. En los scripts de navegador, asegúrese de cargar la biblioteca de promesas de terceros antes de cargar el SDK. En el siguiente ejemplo, el SDK está configurado para utilizar la implementación en la biblioteca de promesas bluebird.

```
AWS.config.setPromisesDependency(require('bluebird'));
```

Para volver a utilizar la implementación de promesas nativa del motor de JavaScript, vuelva a llamar a `setPromisesDependency` y transfiera `null` en vez de un nombre de biblioteca.