2014-09-01 129 views
0

我有一個遞歸函數,我試圖讓它按順序運行,每次都返回諾言。 該代碼是遞歸的,運行良好,但僅適用於for循環中的第一項。從循環中返回一個承諾

實施例:

  • 文件夾:1 - 行
  • 文件夾:11 - OK
  • 文件夾:111 - 行
  • 文件夾:111 - 行
  • 文件夾: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循環的情況下返回promise? PS:如果我使用forEach廁所,它不會被打斷,但是隨後我失去了依次返回文件夾的能力。

實施例:

  • 文件夾:1 - 行
  • 所有異步下載順序完成。
  • 文件夾:11 - OK
  • 文件夾:111 - OK
  • 文件夾:111 - OK
  • 文件夾:2 - 正常
  • 文件夾:12 - OK
+0

對不起,我補充說,收集folderlist – 2014-09-01 12:14:21

回答

4

是的,就像使用任何函數,如果您執行return語句,該函數將停止它正在執行的操作並返回。你應該能夠做到你想用下面做什麼:

編輯:,如果你不需要它們以特定的順序來完成,你可以完成你正在嘗試與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我將嘗試降低該解決方案的一部分。我不需要它們返回命令,我只需要在最後一次調用完成時返回函數 – 2014-09-01 12:18:44

+0

如何在WinJS中翻譯Promise.resolve()?它是WinJS.Promise.as()嗎? – 2014-09-01 12:25:31

+0

感謝您修復它。 OP:'Promise.resolve'的確是'WinJS.Promise.as'。 – 2014-09-01 12:30:04