Estoy tratando de ejecutar una función de devolución de llamada dentro de un bucle for, pero encuentro problemas al ejecutar la función de devolución de llamada. Parece que la función se ejecuta después de que se completa el ciclo for. Por ejemplo, si el bucle for tiene 2 iteraciones, entonces la función se ejecuta solo después de que se ejecuten las dos iteraciones del bucle for. Por lo tanto, la ejecución de la función siempre se realiza después de la última iteración del bucle for for. Lo estoy intentando muy duro y he pasado casi un día hoy mirando ejemplos y finalmente he usado los cierres según el ejemplo proporcionado en el enlace a continuación, pero aún no obtengo el resultado exacto. https://www.geekabyte.io/2013/04/callback-functions-in-loops-in.html
A continuación se muestra el código que estoy usando:
let promoList = []; for(i = 0; i< availablePromoCount; i++){ promoObj = {}; promoObj.maxUsesUser = getAvailablePromoResults[i].MaxUsesUser //getAvailablePromoResults is a list coming from another function not shown here promoObj.promoCode = getAvailablePromoResults[i].PromoCode; // available promo code for this iteration promoList.push(promoObj); (function(clsn){ searchUserUsedPromo(userId, promoList[clsn].promoCode, (error, searchUserUsedPromoResults) => { if (error) { console.log(error); return res.status(500).json({ success: 0, message: "Some other error", error: error, }); } console.log("Iteration of function is ", clsn); // always iteration is last iteration and displays same and last iteration of i console.log("Searched promo code is ", promoList[clsn].promoCode); timesUsed = searchUserUsedPromoResults.length; console.log("Times Used", timesUsed); console.log("Max uses user", promoList[i].maxUsesUser); }); })(i) count++; if(getAvailablePromoResults.length == count){ return res.status(200).json({ success: 1, availablePromoList: availablePromoList, }); } }searchUserUsedPromo() llama a order.model.js para obtener la consulta de base de datos y se ejecuta
searchUserUsedPromo: (userId, promoCode, callback) => { pool.query( `select * from userpromo where UserId = ? and PromoCode = ? and Used = 1`, [ userId, promoCode ], (error, results, fields) => { console.log(results); if (error) { return callback(error); } return callback(null, results); } ); },El bucle no espera la función de devolución de llamada. Es asíncrono. Eso significa que todo lo que hace su ciclo es iniciar la búsqueda y luego pasar inmediatamente a la siguiente iteración del ciclo. Luego, algún tiempo después (después de que el bucle for esté completamente terminado), la búsqueda finaliza y llama a la devolución de llamada. Esta estructura no funcionará. Lo mejor es "prometer" su operación asíncrona para que luego pueda usar async/await con ella. El bucle se detendrá para await una promesa.
Según el código parcial que ha mostrado en su pregunta, aquí hay una versión prometida que permite que el ciclo espere la operación asincrónica:
Resumen de Cambios:
searchUserUsedPromo() se ha cambiado para devolver una promesaasync que usa await await when calling searchUserUsedPromo() so that the bucle for` se detenga.let para declarar todas las variables utilizadas aquíY, aquí está el código:
// promisify this function so it returns a promise that resolves/rejects // when it is complete and resolves with the asynchronously retrieved value searchUserUsedPromo: (userId, promoCode) => { return new Promise((resolve, reject) => { pool.query(`select * from userpromo where UserId = ? and PromoCode = ? and Used = 1`, [userId, promoCode], (error, results, fields) => { if (error) { reject(error); } else { resolve(results); } } ); }); }, async function someFunction(req, res) { try { let promoList = []; for (let clsn = 0; i < availablePromoCount; clsn++) { let promoObj = {}; //getAvailablePromoResults is a list coming from another function not shown here promoObj.maxUsesUser = getAvailablePromoResults[clsn].MaxUsesUser // available promo code for this iteration promoObj.promoCode = getAvailablePromoResults[clsn].PromoCode; promoList.push(promoObj); let searchUserUsedPromoResults = await searchUserUsedPromo(userId, promoList[clsn].promoCode); console.log("Iteration of function is ", clsn); console.log("Searched promo code is ", promoList[clsn].promoCode); let timesUsed = searchUserUsedPromoResults.length; console.log("Times Used", timesUsed); console.log("Max uses user", promoList[i].maxUsesUser); } res.status(200).json({ success: 1, availablePromoList: availablePromoList, }); } catch (e) { res.status(500).json({ success: 0, message: "Some other error", error: error, }); } }