Estoy tratando de escribir una función, pero parece que no puedo averiguar cómo ejecutar un bucle de llamadas API en una matriz de cadenas, y solo después de que se completen todas las llamadas API para llamar a la función de devolución de llamada. No importa lo que intente, la función falla o la función de devolución de llamada se llama demasiado pronto.
Aquí está mi código:
exports.handler = function (context, event, callback) { const client = context.getTwilioClient(); const sidArr = []; const cc = event.ccSid; const exp = event.expSid; const cvc = event.cvcSid; sidArr.push(cc, exp, cvc); const resArr = []; for (var i = 0; i < sidArr.length; i++) { client .messages(sidArr[i]) .update({ body: '' }) .then((message) => { if (resArray.length == sidArr.length) { callback(null, resArray); } else { resArray.push(message.sid); } }); } };El método de update devuelve una Promise . Recorra la matriz sidArr y llame a los messages y al método de update para cada elemento de la matriz. Almacene la Promise devuelta en una nueva matriz.
Puede esperar a que todas las promesas en una matriz terminen con la función estática Promise.all . El resultado será una matriz de todas las promesas resueltas.
Luego, repite cada resultado una vez más para extraer la propiedad sid .
exports.handler = function (context, event, callback) { const client = context.getTwilioClient(); const sidArr = []; const cc = event.ccSid; const exp = event.expSid; const cvc = event.cvcSid; sidArr.push(cc, exp, cvc); const requests = sidArr.map(message => client .messages(message) .update({ body: "" }) .catch(error => console.log(error)) ); Promise.all(requests) .then(messages => messages.map(({ sid }) => sid)) .then(sids => callback(sids)) };Si no puede usar async y await , puede usar Promise.all() y ejecutarlos en paralelo de esta manera:
Ejecutarlos en paralelo:
let promises = []; for (var i = 0; i < sidArr.length; i++) { promises.push( client .messages(sidArr[i]) .update({ body: '' }) .then((message) => message.sid) ); } Promise.all(promises) .then((results) => callback(null, results)) .catch((err) => callback(err)); Por supuesto, es un poco antipatrón convertir una promesa en una simple devolución de llamada como esta. Realmente debería cambiar la interfaz y devolver la promesa a la persona que llama para que la persona que llama pueda usar .then() y .catch() en la promesa directamente.
Ejecútelos secuencialmente sin async y await :
O, si desea ejecutarlos secuencialmente (no en paralelo) sin usar async y await , puede hacerlo a la antigua usanza para una iteración asíncrona (lo que hicimos antes de async/await ):
function run(sidArr, callback) { let index = 0; let results = []; function next() { // check if we're done and call callback if (index >= sidArr.length) { // ensure callback is always called asynchronously // even if sidArr is empty setImmediate(() => callback(null, results)); return; } // still more to process client .messages(sidArr[index++]) .update({ body: '' }) .then((message) => { // save result and do next iteration of loop results.push(message.sid); next(); }) .catch(callback); } next(); } run(sidArr, putYourCompletionCallbackHere); Ejecútelos secuencialmente con async y await :
Para completar, así es como los ejecutaría secuencialmente cuando puede usar async y await :
async function run(sidArr, callback) { try { let results = []; for (var i = 0; i < sidArr.length; i++) { let data = await client.messages(sidArr[i]).update({ body: '' }); results.push(data.sid); } callback(null, results); } catch (e) { callback(e); } } run(sidArr, putYourCompletionCallbackHere);