2014-09-01 2 views
0

У меня есть рекурсивная функция, и я пытаюсь заставить ее работать последовательно, возвращая обещание каждый раз. Код рекурсивный и работает хорошо, но работает только для первого элемента цикла for.вернуть обещание изнутри цикла for

Пример:

  • папку: 1 - OK
  • папки: 11 - OK
  • папка: 111 - OK
  • папка: 111 - OK
  • папка: 2 - NOT OK
  • Папка: 12 - НЕ ОК
  • Все асинхронные загрузки завершены в последовательности.

Я думаю, что это потому, что, когда я возвращаю обещание изнутри, тогда цикл for прерывается.

function CopySubFolders(folder, destFolder) { 

    // Recursively copy each subfolder 
    return folder.getFoldersAsync() 
    .then(function (folderlist) { 
     if (folderlist.size > 0) { 
      for (var i in folderlist) { 
       var replace = Windows.Storage.CreationCollisionOption.replaceExisting; 
       console.log("create folder: " + folderlist[i].name); 

       return destFolder.createFolderAsync(folderlist[i].name, replace) 
       .then(function (newdest) { 
        return CopySubFolders(folderlist[i], newdest); 
       }); 
      } 
     } 
     else { 
      return WinJS.Promise.as(); 
     } 
    }); 
} 


CopySubFolders(folder, self.localFolder) 
.then(function() { 
    completeFunc("Done"); 
    console.log("All asynchronous downloads completed in sequence."); 
}) 

Любая идея, как вернуть обещание без прерывания цикла for?

PS: Если я использую forEach loo, это не прервется, но тогда я потеряю способность возвращать папки в последовательности.

Пример:

  • папку: 1 - OK
  • Все асинхронные загрузки завершены в последовательности.
  • папки: 11 - OK
  • папка: 111 - OK
  • папка: 111 - OK
  • папка: 2 - OK
  • папки: 12 - OK
+0

жаль, что я добавил часть, обрежь folderlist –

ответ

4

Да, так же, как с любой функцией, если вы выполните оператор return, функция остановит то, что он делает и вернет. Вы должны быть в состоянии сделать то, что вы пытаетесь сделать со следующим:

Edit:, если вам не нужно их завершить в определенной последовательности, вы можете сделать то, что вы пытаетесь сделать с WinJS.Promise.join() (он же Promise.all() в других обещают диалектов) и map (я факторизуя внутреннюю часть здесь, чтобы сократить вложенности):

function CopySubFolders(folder, destFolder) { 
    return folder.getFoldersAsync() 
    .then(function (folderlist) { 
     return WinJS.Promise.join(folderlist.map(function (folder) { 
      return CopyFolder(folder, destFolder); 
     }); 
    }); 
} 

function CopyFolder(folder, destFolder) { 
    var replace = Windows.Storage.CreationCollisionOption.replaceExisting; 
    console.log("create folder: " + folder.name); 

    return destFolder.createFolderAsync(folder.name, replace) 
      .then(function (newdest) { 
       return CopySubFolders(folder, newdest); 
      }); 
} 

в комплекте примечания, пожалуйста, не используйте for...in с массивами. Это плохая идея.

И как немного пережиток этого поста, вот как вы бы иметь возможность создавать папки в последовательности, если вам нужно (хотя это не рекомендуется):

function CopySubFolders(folder, destFolder) { 
    var p = Promise.resolve(); 

    return folder.getFoldersAsync() 
    .then(function (folderlist) { 
     return folderlist.forEach(function (folder) { 
      var replace = Windows.Storage.CreationCollisionOption.replaceExisting; 
      console.log("create folder: " + folder.name); 

      p = p.then(function() {  
       destFolder.createFolderAsync(folder.name, replace) 
       .then(function (newdest) { 
        return CopySubFolders(folder, newdest); 
       }); 
      }); 
     }); 
    }); 

    return p; 
} 

Еще немного чище способ сделать то же самое, как показано на рисунке here, является использование folderlist.reduce():

function CopySubFolders(folder, destFolder) { 
    return folder.getFoldersAsync() 
    .then(function (folderlist) { 
     return folderlist.reduce(function (sequence, folder) { 
      var replace = Windows.Storage.CreationCollisionOption.replaceExisting; 
      console.log("create folder: " + folder.name); 

      return sequence.then(function() {  
       destFolder.createFolderAsync(folder.name, replace) 
       .then(function (newdest) { 
        return CopySubFolders(folder, newdest); 
       }); 
      }); 
     }, Promise.resolve()); 
    }); 
} 
+0

thnkas Я попробую это решение с уменьшить. Я не нуждаюсь в них, чтобы вернуть заказ, мне просто нужна функция, чтобы вернуться, когда последний из вызовов был завершен. –

+0

как вы перекладываете этот Promise.resolve() в WinJS? это WinJS.Promise.as()? –

+0

Спасибо за его исправление. OP: 'Promise.resolve' действительно' 'WinJS.Promise.as'. –

Смежные вопросы