Estaba practicando algo de Javascript nativo y me encontré con este problema. Estoy creando un widget de comentarios e intentando implementar un botón de 'responder'. Para esto, tengo que iterar a través de una cantidad n de comentarios anidados para encontrar el correcto y enviar la respuesta a su atributo 'respuestas'. Este es mi código hasta ahora:
const recursiveSearch = (object, target) => { if(object.id === target) return object; let result; if(object.responses.length > 0) { object.responses.forEach(response => { if(response.id === target) { result = response; console.log('match found') console.log(response) return response } else if(response.responses.length > 0) recursiveSearch(response, target) }) }; console.log('result Is') console.log(result) return result }Los registros muestran el comportamiento esperado muy bien, pero al mirar la declaración de devolución final no está definida. ¿Alguna forma de evitar esto?
Puede simplificar drásticamente su programa utilizando generadores y funciones reutilizables:
function first(it) { for (const v of it) return v } function *search(t, id) { if (t.id == id) yield t for (const r of t.responses) yield *search(r, id) } const mydata = { id: 1, responses: [ { id: 2, responses: [] }, { id: 3, responses: [] }, { id: 4, responses: [ { id: 5, responses: [] }, { id: 6, responses: [] }, { id: 7, responses: [] } ]}, { id: 8, responses: [ { id: 9, responses: [ { id: 10, responses: [] } ]} ]} ]} console.log(first(search(mydata, 8))) // { id: 8, responses: [ ... ] } console.log(first(search(mydata, 100))) // undefined Aún mejor es la opción de hacer que la search sea genérica, aceptando una función de match y next . Ahora puede buscar datos de entrada de cualquier tipo o forma con cualquier campo. Es decir, no está limitado solo a la id y responses :
function first(it) { for (const v of it) return v } function *search(t, match, next) { if (Boolean(match(t))) yield t for (const r of next(t) ?? []) yield *search(r, match, next) } function mysearch(t, id) { return search(t, t => t.id == id, t => t.responses) } const mydata = { id: 1, responses: [ { id: 2, responses: [] }, { id: 3, responses: [] }, { id: 4, responses: [ { id: 5, responses: [] }, { id: 6, responses: [] }, { id: 7, responses: [] } ]}, { id: 8, responses: [ { id: 9, responses: [ { id: 10, responses: [] } ]} ]} ]} console.log(first(mysearch(mydata, 8))) // { id: 8, responses: [ ... ] } console.log(first(mysearch(mydata, 100))) // undefinedSe olvidó de regresar en su otra cosa si, pero tenga en cuenta que está dentro de un forEach, así que tal vez cámbielo a normal o use otra cosa
Debe regresar de la llamada recursiva y asignar nuevamente a la variable de result .
const recursiveSearch = (object, target) => { if (object.id === target) return object; let result; if (object.responses.length > 0) { object.responses.forEach(response => { if (response.id === target) { result = response; console.log('match found') console.log(response) return response } else if (response.responses.length > 0) { result = recursiveSearch(response, target) // <-------------------- } }) }; console.log('result Is') console.log(result) return result } También puede usar una find en lugar de forEach . Esto es más eficiente.
const recursiveSearch = (object, target) => { if (object.id === target) return object; const result = object.responses.find(response => { if (response.id === target) { console.log('match found') console.log(response) return response } else if (response.responses.length > 0) { return recursiveSearch(response, target) } }) console.log('result Is') console.log(result) return result }