以下是我在项目中使用的代码,允许用户上传文件。 对于所选的每个文件," $ scope.upload"函数被异步调用。
因为这些是异步调用,所以每次调用都不依赖于之前的调用。
但我的要求是只有在成功回调函数执行后, 然后下一次上传应该发生,因为每次上传都取决于值 由上次上传返回。
请让我知道如何实现。 注意:$ scope.upload是部分角度文件上传js(https://github.com/danialfarid/ng-file-upload)
$scope.startUploading = function ($files, errFiles, item) {
//$files: an array of files selected
for (var idx = 0; idx < $files.length; idx++) {
var $file = $files[idx];
(function (index) {
$scope.upload[index] = $upload.upload({
url: "../UploadCommentAttachment",
method: "POST",
file: $file,
data: item
}).success(function (responseData, status, headers, config) {
item.AuditCommentAttachments.push(responseData);
item.CommentId = responseData.CommentId;
item.AuditId = responseData.AuditId;
item.Operation = "EDIT";
item.CommentAttachmentID = responseData.CommentAttachmentID;
}
});
})(idx);
} ///-- for loop end
} // startuploading end
答案 0 :(得分:3)
顺序执行异步操作的方法是使用.then
方法派生的promise来链它们。后续承诺使用的值应在.then
方法中返回。
function sequentiallyExecute = function (opList) {
//create initial object
var passedObject = {};
passedObject.dataList = [];
passedObject.response = {};
//create initial promise
var promise = $q.when(passedObject);
//sequentially execute opList
angular.forEach(opList, function(op) {
promise.then(function (passedObject) {
var iPromise = asyncOperation(op, passedObject);
iPromise.then(function onFulfulled(response) {
//save response for chaining
passedObject.response = response;
//push data to list
passedObject.dataList.push(response.data);
//return object for chaining
return passedObject;
});
//return promise for chaining
return iPromise;
});
});
//return promise to client
return promise;
};
在客户端代码中,检索最终数据。
(sequentiallyExecute(opList)
).then (function onFulfilled(passedObject) {
$scope.dataList = passedObject.dataList;
}).catch (function onRejected(error) {
console.error(error);
});
有关链接的详细信息,请参阅AngularJS $q Service API Reference -- chaining promises。
不使用.success
方法(不可链接),而是使用.then
方法( 可链接)。
function asychOperation(op, passedObject) {
var $file = op.$file
var item = passedObject.item;
var httpPromise = $upload.upload({
url: "../UploadCommentAttachment",
method: "POST",
file: $file,
data: item
});
var derivedPromise = httpPromise.then(function (response) {
var data = response.data
passedObject.dataList.push(data);
var newItem = {};
newItem.CommentId = data.CommentId;
newItem.AuditId = data.AuditId;
newItem.Operation = "EDIT";
newItem.CommentAttachmentID = data.CommentAttachmentID;
passedObject.item = newItem;
});
var promise = derivedPromise.then (function onFulfilled() {
//return object for chaining
return passedObject;
});
//return promise for chaining
return promise;
};
.success
服务的.error
和$http
方法已被弃用。而是使用.then
和.catch
方法。有关详细信息,请参阅 AngularJS $http Service API Reference -- deprecation notice
因为调用promise的.then
方法会返回一个新的派生promise,所以很容易创建一个promise链。
可以创建任意长度的链,并且由于可以使用另一个承诺(将进一步推迟其解析)来解决承诺,因此可以在链中的任何点暂停/推迟承诺的解析。这使得实现强大的API成为可能。 1
答案 1 :(得分:1)
我已经从ng-file-upload修改了一个小提琴,逐个处理帖子,并使用前一个帖子的响应到当前帖子。请检查my fiddle
这是javascript代码的一部分,可以解决这个问题
function sequentialFileUploadWithReduce(values) {
var result = ''
var dfd = $q.defer();
dfd.resolve();
return values.reduce(function(currentValue, nextValue, index, values) {
return Upload.upload({
url: "https://angular-file-upload-cors-srv.appspot.com/upload",
method: "POST",
data: currentValue
}).then(function(resp) {
// file is uploaded successfully
//debugger;
result += "Uploading file " + index++;
console.log("Uploading file " + index);
nextValue.item = resp;
}, function(resp) {
// handle error
}, function(evt) {
// progress notify
});
}, dfd.promise).then(function(responce) {
return result;
});
}
希望这会有所帮助。另请查看控制台和网络选项卡以验证解决方案是否正常工作。
答案 2 :(得分:1)
下面的代码为我完成了所需的工作,顺序执行异步操作,没有链接。
$scope.startUploading = function ($files, item)
{
var cntr = 0;
function next()
{
if (cntr < $files.length)
{
$scope.upload[cntr] = $upload.upload({
url: "../UploadCommentAttachment",
method: "POST",
file: $files[cntr],
data: item
}).then(function (responseData) { item.AuditCommentAttachments.push(responseData.data);
item.CommentId = responseData.data.CommentId;
item.AuditId = responseData.data.AuditId;
item.Operation = "EDIT";
item.CommentAttachmentID = responseData.data.CommentAttachmentID;
cntr++;
next();
});
}
}
next();
}