2017-02-08 3 views
1

Ich möchte viele Bilder (1000 +) herunterladen, so dass ich das Array in Stücke der angegebenen Größe aufteilen und sie nacheinander herunterladen. Die Downloads basieren auf Versprechen und werden aufgelöst, sobald ein Chunk fertig ist. Ohne Verwendung Brocken alles funktioniert gut, aber mit dieser Implementierung geschieht Folgendes:node.js rekursive Download von Chunked-Array mit Versprechen

console.log("Promise Recursive resolved", paths); 

in der Funktion downloadRecursive aufgerufen, sobald es fertig ist, aber es löst nicht wie erwartet, so

console.log("Finished"); 

nicht funktioniert in der downloadAll-Funktion aufgerufen werden.

function downloadAll(folder, full_size, images) { 
    return new Promise(function (resolve, reject) { 
     // Chunks of all images [ [1,2,3,4,5], [6,7,8,9,10], [...] ] 
     let grouped_images = chunk(images, 5); 

     downloadRecursive(folder, full_size, grouped_images, 1, []).then(function (e) { 
      console.log("Finished"); 
      resolve(e); 
     }).catch(function() { 
      reject(); 
     }); 
    }); 
} 


function downloadRecursive(folder, full_size, all, part, paths) { 
    return new Promise(function (resolve, reject) { 
     if(part > all.length){ 
      console.log("Promise Recursive resolved", paths); 
      resolve(paths); 
     } 

     downloadImages(folder, all[part-1], full_size).then(function (e) { 
      paths.push(e); 
      return downloadRecursive(folder, full_size, all, part+1, paths); 
     }); 
    }); 
} 


function downloadImages(folder, images, full_size=true) { 
    [...] 

    return Promise.all(images.map(function (image) { 
     [...] 
     return doDownload(...); 
    })); 
} 

function doDownload(url, path, full_size){ 
    returns promise 
} 
+2

Sie finden Bluebirds 'Promise.map()' mit seiner Nebenläufigkeitsoption sehr nützlich. Es löst solche Probleme. Wie man eine große Anzahl von asynchronen Operationen mit nicht mehr als N im Flug zur gleichen Zeit ausführt. – jfriend00

+0

Das Erstellen neuer Versprechen ist ein Anti-Pattern. Anstatt "neues Versprechen (...) ..." zu machen und dann "ablehnen/ablehnen" von ".dann" und ".catch" zu nennen, ziehe das "neue Versprechen" ab und gib einfach deine Versprechenskette zurück. Siehe: http://jf.io/2016/10/09/projects#anti-patterns-explicit-construction-promises-everywhere –

+0

Ich stimme dem oben, und das Problem könnte sein, dass Sie nicht nach dem Aufruf 'zurückgeben resolve' in 'downloadRecursive', so dass' downloadImages' um eine zusätzliche Zeit läuft und dies fehlschlagen kann. –

Antwort

0

vielmehr einen rekursiven Aufruf als verwenden, versuchen array#reduce verwenden wie so

function downloadAll(folder, full_size, images) { 
    return chunk(images, 5) 
    .reduce((promsie, chunk) => 
     promise.then((array) => 
      downloadImages(folder, chunk, full_size) 
      .then(result => 
       array.concat(result) 
      ) 
     ), Promise.resolve([]) 
    ); 
} 


function downloadImages(folder, images, full_size=true) { 
    [...] 
    return Promise.all(images.map(function (image) { 
     [...] 
     return doDownload(...); 
    })); 
} 

function doDownload(url, path, full_size){ 
    returns promise 
} 
0

Sie müssen den Fehler fangen und finden Sie heraus, welche die Kette bricht, so können Sie debuggen, was auf dem Weg passiert

downloadRecursive(folder, full_size, grouped_images, 1, []).then(function (result) { 
     console.log("Finished"); 
     resolve(result); 
    }).catch(function (error) { 
     console.log("error in recursion:", error); 
     reject(error); 
    }); 

im schlimmsten Fall, wenn Sie ein paar Fehler in 1000+ Bilder nicht vermeiden können, dann können Sie einen Haken() Block an den problematischen Code hinzufügen möchten, und nur den Fehler ein unterdrücken: d erlauben, dass die Schleife fortfährt.

+0

Die Kette ist nicht durch einen Fehler unterbrochen ... Fakt ist, dass Promise, die in 'downloadRecursive' zurückgegeben wird, nur einmal aufgelöst wird, wenn' part> all.length' ... und die Rekursion sowieso keine Verkettung durchführt! er könnte (glaube ich) 'auflösen (downloadRecursive (...))' anstelle von 'return downloadRecursive' - aber das ist immer noch sehr hässlicher Code, wenn es überhaupt funktioniert ... –

+0

Mehrere Definitionen zur Wortkette – wayofthefuture

+0

ernst? Semantik? Ich spreche über (die Nichtexistenz von) der Versprechenskette - wie wird die endgültige "Lösung" dazu führen, dass sie die Rekursion hochgeht, um das Versprechen zu lösen, das beim ersten Aufruf erstellt wurde? –

Verwandte Themen