una son solo sincronas que promesas permite manejar las función funciones expresión entendiendo ejecucion controlar await async asincrónica asincronia asincronas asincrona javascript node.js

son - promesas javascript



¿La mejor manera de llamar a una función asíncrona dentro del mapa? (5)

2019

advertencia con Promise.all, no se ejecutan en el orden exacto, algunos servidores no pueden admitir consultas de ejecución simultánea o llamadas de API.

Más bibliotecas nuevas hacen que mis aplicaciones de una sola página tengan más de 4 megas construidas. Así que he decidido no agregar más nuevas librerías como lodash, etc., que se pueden reemplazar con código. Me esperan buenas soluciones para usar con el mapa:

rows.map ( ( record ) => { try { (async () => { let col = await client.query(`SELECT * FROM customers`); })(); } catch (err) { console.log(err); } });

Estoy mapeando sobre una matriz y para uno de los valores de retorno del nuevo objeto, necesito hacer una llamada asincrónica.

var firebaseData = teachers.map(function(teacher) { return { name: teacher.title, description: teacher.body_html, image: urlToBase64(teacher.summary_html.match(/src="(.*?)"/)[1]), city: metafieldTeacherData[teacher.id].city, country: metafieldTeacherData[teacher.id].country, state: metafieldTeacherData[teacher.id].state, studioName: metafieldTeacherData[teacher.id].studioName, studioURL: metafieldTeacherData[teacher.id].studioURL } });

La implementación de esa función se verá más o menos como

function urlToBase64(url) { request.get(url, function (error, response, body) { if (!error && response.statusCode == 200) { return "data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString(''base64''); } }); }

No estoy claro cuál es el mejor enfoque para hacer esto ... ¿promesas? Devoluciones de llamada anidadas? ¿Usar algo en ES6 o ES7 y luego transpilar con Babel?

¿Cuál es la mejor forma actual de implementar esto?

¡Gracias!


Estoy usando una función asincrónica sobre la matriz. Y no usando array.map, sino una función for. Es algo como esto:

const resultingProcessedArray = async function getSomeArray() { try { let { data } = await axios({url: ''/myUrl'', method:''GET''}); //initial array let resultingProcessedArray = []; for (let i = 0, len = data.items.length; i < len; i++) { let results = await axios({url: `/users?filter=id eq ${data.items[i].someId}`, method:''GET''}); let domainName = results.data.items[0].domainName; resultingProcessedArray.push(Object.assign(data.items[i], {domainName})); } return resultingProcessedArray; } catch (err) { console.error("Unable to fetch the data", err); return []; } };


Puede usar async.map .

var async = require(''async''); async.map(teachers, mapTeacher, function(err, results){ // results is now an array of stats for each file }); function mapTeacher(teacher, done) { // computing stuff here... done(null, teacher); }

tenga en cuenta que todos los profesores se procesarán en paralelo; también puede usar estas funciones:

mapSeries(arr, iterator, [callback]) asigna uno por uno

mapLimit(arr, limit, iterator, [callback]) asigna un limit mapas al mismo tiempo


Un enfoque es Promise.all (ES6) .

Esta respuesta funcionará en el Nodo 4.0+. Las versiones anteriores necesitarán un polyfill o biblioteca Promise. También he usado las funciones de flecha ES6, que podría reemplazar con function regulares para Nodo <4.

Esta técnica envuelve manualmente request.get con una Promesa. También podría usar una biblioteca como request-promise .

function urlToBase64(url) { return new Promise((resolve, reject) => { request.get(url, function (error, response, body) { if (!error && response.statusCode == 200) { resolve("data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString(''base64'')); } else { reject(response); } }); }) } // Map input data to an Array of Promises let promises = input.map(element => { return urlToBase64(element.image) .then(base64 => { element.base64Data = base64; return element; }) }); // Wait for all Promises to complete Promise.all(promises) .then(results => { // Handle results }) .catch(e => { console.error(e); })


actualización en 2018: la función asincrónica Promise.all dentro de la devolución de llamada del mapa es más fácil de implementar:

let firebaseData = await Promise.all(teachers.map(async teacher => { return { name: teacher.title, description: teacher.body_html, image: await urlToBase64(teacher.summary_html.match(/src="(.*?)"/)[1]), city: metafieldTeacherData[teacher.id].city, country: metafieldTeacherData[teacher.id].country, state: metafieldTeacherData[teacher.id].state, studioName: metafieldTeacherData[teacher.id].studioName, studioURL: metafieldTeacherData[teacher.id].studioURL } })); async function urlToBase64(url) { return request.get(url, function (error, response, body) { if (!error && response.statusCode == 200) { return "data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString(''base64''); } }); }

Edit @ 2018/04/29: pongo el ejemplo general para todos:

Editar @ 2019/06/19: async / await debería tener try / catch para manejar el error, si no, arrojaría un mensaje de advertencia;

let data = await Promise.all(data.map(async (item) => { try { item.fetchItem = await fetchFunc(item.fetchParams); return item; } catch(err) { throw err; } });