2011-02-19 12 views
16

La función siguiente imprime marcadores de Chrome en una carpeta recursivamente. ¿Cómo podría alterar la función siguiente para llamar a otra función después de procesar el ciclo recursivo final? chrome.bookmarks.getChildren() es asíncrono lo que hace que sea difícil saber cuándo la función está procesando todo.Devolución de llamada después del final de la función recursiva asincrónica

Gracias.

for (var i = 0; i < foldersArray.length; i++) { 
     // The loop makes several calls with different folder IDs. 
     printBookmarks(foldersArray[i]); 
    } 

    // I'd like any code here to be run only after the above has 
    //finished processing  

    function printBookmarks(id) { 
     chrome.bookmarks.getChildren(id, function(children) { 
      children.forEach(function(bookmark) { 
       console.debug(bookmark.title); 
       printBookmarks(bookmark.id); 
      }); 
     }); 
    } 

EDIT: Lo siento, no creo que haya sido claro en el ejemplo de código inicial. He actualizado el código para mostrar el problema que estoy teniendo con la función asincrónica llamando a la función varias veces. Me gustaría que cualquier código después de la función printBookmarks llame para esperar a que todas las funciones printBookmarks finalicen el procesamiento.

Respuesta

0

podría ser una mejor manera de hacer esto, pero usted podría agregar un parámetro de profundidad, algo así como

printBookmarks('0', 0); 

function printBookmarks(id, depth) { 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id, depth + 1); 
     }); 
     if(depth == 0) yourFunction(); 
    });  
} 

EDITAR en respuesta a comentar

Esta es una variación en otra respuesta para un enfoque ligeramente diferente.

runCount = 0; 
for (var i = 0; i < foldersArray.length; i++) { 
    // The loop makes several calls with different folder IDs. 
    printBookmarks(foldersArray[i]); 
    runCount++; 
} 

while(runCount > 0) { // sleep for 10ms or whatnot} 
// I'd like any code here to be run only after the above has 
// finished processing.  

function printBookmarks(id) { 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id); 
      runCount--; 
     }); 
    }); 
} 
+0

Lo siento, no creo que haya sido claro con mi código de ejemplo. Tu código funciona para una sola llamada para imprimir marcadores, pero me gustaría saber cuándo se terminan todas las llamadas a printBookmarks (realizadas de forma asíncrona). He actualizado mi código. Gracias. – usertest

25

Sus instancias de métodos asíncronos pueden ser todos ejecutan a la vez, y que no saben cuántos habrá de antemano. Por lo tanto, deberá mantener el conteo y luego usar una devolución de llamada cuando finalice el último método asincrónico.

for (var i = 0; i < foldersArray.length; i++) { 
    // The loop makes several calls with different folder IDs. 
    printBookmarks(foldersArray[i], thingsToDoAfter); 
} 

function thingsToDoAfter() { 
    // I'd like any code here to be run only after the above has 
    // finished processing. 
} 

var count = 0; 

function printBookmarks(id, callback) { 
    count++; 
    chrome.bookmarks.getChildren(id, function(children) { 
     children.forEach(function(bookmark) { 
      console.debug(bookmark.title); 
      printBookmarks(bookmark.id, callback); 
     }); 
     count--; 
     if (count === 0 && callback) 
      callback(); 
    }); 
} 
+1

y pensé que acabo de inventar este: p – nischayn22

+0

Gracias por esta solución. En mi caso, tuve detalles implícitos en mi devolución de datos que indicaban que era la iteración final, así que no usé el recuento. Pero me encantó el concepto de devolución de llamada. ¡Gracias! –

0

Puede guardar todas sus llamadas completadas en una variable y compararlas con la cantidad de marcadores que desea procesar. Cuando llega al final (el recuento de terminaciones equivale a la cantidad de marcadores para procesar), entonces ejecuta su función final.

Una respuesta a un problema similar es aquí, con el código que se puede utilizar como guía:

How do I load a variable number of scripts with jQuery.getScript() before running javascript code?

+0

Creo que el problema es que no sé la cantidad de marcadores que se procesarán hasta que se procesen. – usertest

2

que he tenido recientemente para solucionar este problema. La solución fue similar a la de Eric, pero descubrí que necesitaba que la variable de recuento fuera local para la función. Aquí es cómo resolvería esto:

for(var i=0;i<foldersArray.length; i++){ 
    // The loop make's several call's with different folder ID's. 
    var printed_children = 0; 
    printBookmarks(foldersArray[i],function() { 
    printed_children++; 
    if(printed_children == foldersArray.length){ 
     // You know you are done! 
    } 
    }); 
} 
// I'd like any code here to be run only after the above has 
//finished processing. 


function printBookmarks(id,finished_callback) { 
    // the printed_children count is local so that it can keep track of 
    // whether or not this level of recursion is complete and should call 
    // back to the previous level 
    var printed_children = 0; 
    chrome.bookmarks.getChildren(id, function(children) { 
    children.forEach(function(bookmark) { 
     console.debug(bookmark.title); 
     // added a callback function to the printBookmarks so that it can 
     // check to see if all upstream recursions have completed. 
     printBookmarks(bookmark.id,function() { 
     printed_children++; 
     if(printed_children == children.length){ 
      finished_callback(); 
     } 
     }); 
    }); 
    if(children.length == 0){ 
     finished_callback(); 
    } 
    }); 
} 

Es un poco feo, pero debería funcionar.

0

usted puede hacer algo como esto JQFAQ.com. Estoy actualizando para los usos futuros.

Cuestiones relacionadas