Estoy tratando de iterar una lista de objetos que tengo, y quiero verificar si tiene el texto 'Agregar al carrito', luego obtener su ID de producto y luego salir del ciclo (ya que solo quiero el primer elemento disponible).
Sin embargo, he intentado romperlo, pero se ejecuta a través de todos los elementos independientemente, y parece que no puedo entender por qué. ¿Tiene que ver con async await? Estoy usando titiritero.
let putterID; await putters.every(async (putter) => { let inStock = await putter.$eval('.product-details .tocart a', el => el.innerHTML); inStock = inStock.trim(); if (inStock == "Add To Cart") { putterID = await putter.$eval('.product-details .price', el => el.getAttribute('data-publishproductid')); console.log(`Found the first available putter with ID: ${putterID}`); return false; } });Las funciones integradas de orden superior no funcionan bien con las funciones asincrónicas. No podrá obtener .every() para hacer lo que quiera de esa manera.
Si quieres hacer un bucle for, ¿por qué no simplemente hacer un bucle for?
for (const putter of putters) { let inStock = await putter.$eval('.product-details .tocart a', el => el.innerHTML); inStock = inStock.trim(); if (inStock == "Add To Cart") { putterID = await putter.$eval('.product-details .price', el => el.getAttribute('data-publishproductid')); console.log(`Found the first available putter with ID: ${putterID}`); break; } } La razón por la que .every() no funciona de la manera deseada es por lo siguiente: .every() toma una función síncrona, la llama y, si todos los valores devueltos son verdaderos, .every .every() devolverá verdadero , de lo contrario devolverá falso. Pasaste una función asíncrona, que, recuerda, una función asíncrona es realmente lo mismo que una función síncrona que devuelve una promesa, eso es todo. Por lo tanto, para cada elemento en putters , se llamará a la devolución de llamada, y la devolución de llamada siempre devolverá una promesa, que es veraz, lo que hace que .every .every() devuelva true (que luego espera sin motivo; true no es una promesa, así que esperarla no hace nada). Tenga en cuenta que nada realmente esperó a que estas devoluciones de llamada terminaran de ejecutarse. Terminarán más tarde, a su tiempo.
El uso de every método en Array parece estar completamente explicado por Scotty Jamison. Dado que la función asíncrona devuelve un valor de retorno encerrado en Promise , el valor de retorno de la función que es un parámetro de every método en su código es Promise<void|false> , que se evalúa como verdadero.
Una cosa más, si usa for loop y async/await , solo puede manejar una tarea a la vez. Por lo tanto, no puede beneficiarse de la concurrencia. Por lo tanto, puede usar el contador de la siguiente manera para verificar cada punto final y obtener el primer resultado que desea.
function getPutterID(putters) { return new Promise((res, rej) => { let count = putters.length; let complete = false; let putterID = ''; async function checkPutter(putter) { let inStock = await putter.$eval('.product-details .tocart a', el => el.innerHTML); inStock = inStock.trim(); count--; if (inStock == "Add To Cart" && !complete) { complete = true; console.log(`Found the first available putter with ID: ${putterID}`); res(putter.$eval('.product-details .price', el => el.getAttribute('data-publishproductid'))); } if (!count) rej(); } putters.forEach(putter => checkPutter(putter)); }); } const putterID = await getPutterID(putters); Creé este código asumiendo que el putterID se obtendrá incondicionalmente, pero no está completo, por lo que debe modificarse según la situación. Por ejemplo, si hay demasiados putters , es posible que deba controlar la cantidad de funciones asíncronas que se ejecutan simultáneamente en el checkPutter .