我必须使用 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/