Estoy trabajando en la migración de una base de datos. Esto requiere consultar una base de datos, obtener una matriz de registros y realizar un conjunto de operaciones asíncronas para insertar los datos en la nueva base de datos. Para mantener la coherencia de los datos, quiero insertar los registros uno a la vez, por lo que quiero que cada operación se ejecute secuencialmente. La única forma que he encontrado para hacer esto es usando la recursividad.

¿Existe una forma más limpia de hacer esto mismo? Sé que hay una biblioteca llamada async https://caolan.github.io/async/v3/ que nunca había probado antes.

El método recursivo que he escrito se ve así:

const insertItem = async (data) => {
    let item = data[0];

    if (!item) {
        //I am done return
        return;
    }

    try {
        //Do multiple await calls to insert record into new database
    } catch (e) {
        //Recover from error (DB rollbacks, etc)
    } finally {
        //Remove inserted or failed item from collection.
        data.shift();
        await insertItem(data);
    }
};

//Query original database
getInfo().then((data) => insertItem(data));
0
aolivera 27 ago. 2020 a las 08:37

2 respuestas

La mejor respuesta

Puede usar el bucle de sincronización for...of, esperará la respuesta HTTP.

const dataArr = ['data1', 'data2', 'data3'];

async function processItems(arr){
  for(const el of arr) {
    const response = await insertData(el);    
    // add some code here to process the response.
  }
};

processItems(dataArr);

1
xMayank 27 ago. 2020 a las 05:50

El código publicado logra iterar a través de la colección de datos (una matriz) recuperada de la primera base de datos usando data.shift para mutar la matriz de argumentos antes de llamar a la función única que maneja todo de forma recursiva.

Para limpiar esto, elimine shift y las llamadas recursivas dividiendo la función de procesamiento de datos en dos:

  • una función para recorrer los datos recuperados de la primera base de datos,
  • una segunda función para insertar registros en la segunda base de datos según sea necesario.

Esto elimina la necesidad de la cláusula .finally y deja la estructura del código luciendo más como

async function insertData(data) {
    for( let index = 0 ; index < data.length; ++index) {
        await insertItem( data[index]);
    }
}

async function insertItem( data) {
    try {
        //Do multiple await calls to insert record into new database
    } catch (e) {
        //Recover from error (DB rollbacks, etc)
        // throwing an error here aborts the caller, insertData()
    }
}

getInfo().then( insertData).catch( /*... handle fatal error ...*/);

Dependiendo del estilo preferido, insertItem podría declararse como función anidada dentro de insertData para mantener su apariencia ordenada, y insertData podría escribirse como un argumento de función anónimo de la llamada then después de getInfo().

Es posible, por supuesto, realizar operaciones asíncronas secuencialmente por otros medios, pero usar await dentro de una función async es quizás el método de codificación más simple.

0
traktor53 27 ago. 2020 a las 07:03