javascript - 使用 CordovFile 依赖项创建嵌套文件夹

标签 javascript angularjs ionic-framework promise

我必须使用 ionic 框架在 Android 手机上创建嵌套文件夹。 问题是它是一个异步请求,因此在完成第一个文件夹之前,它会转到下面的代码在第一个文件夹中创建第二个文件夹,因为尚未创建文件夹,所以会出现错误。

我搜索到它可以通过 Angular $q 服务来解决,我尝试了但没有工作,老实说我不知道​​它是如何工作的,下面是我的代码。

Controller

if( $scope.projectDetails.clientId == null && $scope.projectDetails.locationId == null ){
            // insert a row in client table
            var parameters=[$scope.projectDetails.clientName];
            NewProject.insertClient(parameters).then(function(result){
               $scope.projectDetails.clientId = result.insertId;
               // create folder with this name in Renewate folder
               ProjectCreated.createFolder("Renewate",$scope.projectDetails.clientName).then(function(resolve){
                // create new location
                var parameters=[$scope.projectDetails.clientId, $scope.projectDetails.locationName];
                NewProject.insertLocation(parameters).then(function(result){
                    $scope.projectDetails.locationId = result.insertId;
                    // create folder with this name in Renewate folder
                    var folderPath = "Renewate"+"/"+$scope.projectDetails.clientName;
                    ProjectCreated.createFolder(folderPath, $scope.projectDetails.locationName).then(function(resolve){
                          var parameters=[$scope.projectDetails.projectName, $scope.projectDetails.locationId];
                          NewProject.insertProject(parameters).then(function(result){
                              $scope.projectDetails.projectId = result.insertId;
                              var folderPath = "Renewate"+"/"+$scope.projectDetails.clientName+"/"+$scope.projectDetails.locationName;
                              ProjectCreated.createFolder(folderPath, $scope.projectDetails.projectName).then(function(resolve){ 
                                  //$state.go('renewate3');
                              });
                          });
                    });

                });
            });
          });
        }

服务

createFolder: function(folderPath, folderName){
          var q = $q.defer();
          $ionicPlatform.ready(function () {
              $cordovaFile.createDir(cordova.file.externalRootDirectory+folderPath, folderName, true)
              .then(function (success) {
                q.resolve(result);
              },
              function (error) {
                  q.reject(error);
                  alert("error");
              });
          });
          return q.promise;
        },

请告诉我我错在哪里。

最佳答案

您的代码应该可以工作,但我不确定您是否确实说过这个实际代码版本中发生了错误。如果发生错误,很难准确找出错误所在,因为它非常困惑。

重写服务

查看服务中的 createFolder 函数,您已经实现了所谓的 deferred anti-pattern .

$ionicPlatform.ready 已经返回一个 promise (请参阅 documentation ),因此无需像您现在所做的那样创建新的 promise 。您应该返回已经存在的 promise ,例如

return $ionicPlatform.ready(function () {
    return $cordovaFile.createDir(cordova.file.externalRootDirectory+folderPath, folderName, true);
});

请注意,$cordovaFile.createDir will throw an error如果失败,并且由于您没有使用结果/返回值,您可以简单地返回而不带 then 并在更高级别的 .catch() 中处理错误。

我对 Ionic 不太熟悉,无法说出什么是最佳实践,什么不是,但我会研究一下是否真的有必要将 createFolder() 函数包装在 $ 中ionicPlatform.ready,因为如果调用它会直接解析并且它已经准备好了。

重写你的 promise 链 Promise 的一个好处是我们可以摆脱 callback hell当你有很多需要回调的异步函数时,就会发生/pyramid of doom。您所做的是以嵌套方式使用 promise ,这并没有真正使其对人眼来说既不更容易也不更具可读性。您可能需要考虑将函数重构为更具可读性的内容。

当您从 .then() 返回一个 Promise 时,它​​将等到该 Promise 解决后再继续执行下一个 Promise。当您从 .then() 处理程序返回一个值时,它将被包装并解析为 Promise 链中的下一个函数。因此,您可以将代码重写为如下所示。

定义函数

function createFirstFolder(result){
     $scope.projectDetails.clientId = result.insertId;
     // create folder with this name in Renewate folder
     return ProjectCreated.createFolder("Renewate", $scope.projectDetails.clientName);
}

function createNewLocation(){
    // create new location
    var parameters= [$scope.projectDetails.clientId, $scope.projectDetails.locationName];
    return NewProject.insertLocation(parameters);
}


function createSecondLevelFolder(result){
    $scope.projectDetails.locationId = result.insertId;
    // create folder with this name in Renewate folder
    var folderPath = "Renewate"+"/"+$scope.projectDetails.clientName;
    return ProjectCreated.createFolder(folderPath, $scope.projectDetails.locationName);
}

function insertNewProject(){
      var parameters = [$scope.projectDetails.projectName, $scope.projectDetails.locationId];
      return NewProject.insertProject(parameters);
}

function createNewProjectFolder(result){
    $scope.projectDetails.projectId = result.insertId;
    var folderPath = "Renewate"+"/"+$scope.projectDetails.clientName + "/" + $scope.projectDetails.locationName;
    return ProjectCreated.createFolder(folderPath, $scope.projectDetails.projectName);
}

然后这样称呼他们

if( $scope.projectDetails.clientId == null && $scope.projectDetails.locationId == null ){
    // insert a row in client table
    var parameters=[$scope.projectDetails.clientName];

    NewProject.insertClient(parameters)
      .then(createFirstFolder)
      .then(createNewLocation)
      .then(createSecondLevelFolder)
      .then(insertNewProject)
      .then(createNewProjectFolder)
      .then(function(){
        //$state.go('renewate3'); ?
      })
      .catch(function(err) {
        //Handle error
      });
}

这应该更容易观察并且更容易调试!

关于javascript - 使用 CordovFile 依赖项创建嵌套文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41457429/

相关文章:

javascript - 菜单中的下拉列表在单击之前消失

javascript - Angularjs http post 到 c# 不起作用

javascript - 在 AngularJS 中如何从服务本身内部的回调修改服务属性

javascript - 在不使用 ng-click 的情况下使用 Ionic + Cordova + AngularJS 显示联系人列表

javascript - 身份验证在 ionic 和 Firebase 中始终处于事件状态

html - 如何仅设置有序列表项的样式?没有嵌套在里面的无序列表项

javascript - 使用 setInterval 方法并要求 jQuery 替代

javascript - venn.js - JS 维恩图 - 无法复制示例代码

javascript - 通过 phpmailer 发送电子邮件不会返回 Javascript 响应

javascript - AngularJS过滤器: Return array of objects not matching expected string