我有一系列图像,我会迭代并将每个图像上传到远程服务器。上传文件后,我使用结果获取文件名并推送到另一个数组。
我遇到的问题是并非所有结果都被推送到阵列。我试图构建一个包含所有上传图像结果的数组。以下代码在lastTask
循环结束之前执行forEach
:
/**
* Upload picture
*/
$scope.upload = function () {
var token = window.localStorage.getItem('yourTokenKey');
var defer = $q.defer();
var promises = [];
var options = {
fileKey: "image",
fileName: " test.png",
chunkedMode: true,
mimeType: "image/png",
headers: {'x-auth-token': token}
};
function lastTask() {
alert(promises);
$scope.images = [];
$scope.hide();
$scope.showAlert();
$scope.putQc();
alert('finish').then(function () {
defer.resolve();
});
}
angular.forEach($scope.images, function (image) {
$cordovaFileTransfer.upload("http://server.com/file/upload", image, options).then(function (result) {
// Success!
promises.push(result.response + '.jpg');
alert(JSON.stringify(result));
console.log("SUCCESS: " + JSON.stringify(result.response));
// Error
}, function (err) {
alert(JSON.stringify(err));
console.log("ERROR: " + JSON.stringify(err));
// constant progress updates
}, function (progress) {
$scope.show();
});
});
$q.all(promises).then(lastTask);
return defer;
};
答案 0 :(得分:3)
如果我是正确的,那么您的promises
数组是问题所在,而不是推送来自$cordovaFileTransfer.upload
的承诺,而是推送您获得的结果字符串。
第二个问题,我认为你所做的是承诺anti-pattern,这里不需要$q.defer()
。
(第三,可能是无关紧要的,JSON.stringify
并非真正需要,并希望alert
由您定义)
我会把它重写为:
/**
* Upload picture
*/
$scope.upload = function () {
var token = window.localStorage.getItem('yourTokenKey');
var promises = [], results; //CHANGED
var options = {
fileKey: "image",
fileName: " test.png",
chunkedMode: true,
mimeType: "image/png",
headers: {'x-auth-token': token}
};
function lastTask() {
alert(results); //CHANGED
$scope.images = [];
$scope.hide();
$scope.showAlert();
$scope.putQc();
return alert('finish'); //CHANGED
}
promises = $scope.images.map(function (image) { //CHANGED
return $cordovaFileTransfer.upload("http://server.com/file/upload", image, options).then(function (result) { //CHANGED
// Success!
results.push(result.response + '.jpg'); //CHANGED
alert(JSON.stringify(result));
console.log("SUCCESS: " + JSON.stringify(result.response));
// Error
}, function (err) {
alert(JSON.stringify(err));
console.log("ERROR: " + JSON.stringify(err));
throw err;
// constant progress updates
}, function (progress) {
$scope.show();
});
});
return $q.all(promises).then(lastTask); //CHANGED
};
答案 1 :(得分:2)
问题是你没有将promises推送到你的promise数组中。您(最终)将正常值推送到数组中,但在您在空数组或近空数组上运行$q.all
之前不会。
$scope.upload = function() {
var token = window.localStorage.getItem('yourTokenKey');
var promises = [];
var options = {
fileKey: "image",
fileName: " test.png",
chunkedMode: true,
mimeType: "image/png",
headers: {
'x-auth-token': token
}
};
function lastTask(results) {
alert(results);
$scope.images = [];
$scope.hide();
$scope.showAlert();
$scope.putQc();
return results; // keeping the promise chain useful
}
angular.forEach($scope.images, function(image) {
var promiseForUpload = $cordovaFileTransfer.upload("http://server.com/file/upload", image, options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
return result.response + '.jpg'; // this will be the promised value
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
throw err; // re-throwing the error so the q.all promise is rejected
}, function(progress) {
$scope.show();
});
promises.push(promiseForUpload);
});
return $q.all(promises).then(lastTask); // returns a promise for results
};
老实说,虽然我会彻底摆脱中级的东西:
$scope.upload = function() {
var token = window.localStorage.getItem('yourTokenKey');
var options = { /* stuff */ };
function lastTask(results) { // I wouldn't bake this into the $scope.upload, but do it as a result of calling $scope.upload (i.e. with .then).
alert(results);
$scope.images = [];
$scope.hide();
$scope.showAlert();
$scope.putQc();
return results; // keeping the promise chain useful
}
var promises = $scope.images.map(function(image){
return $cordovaFileTransfer.upload("http://server.com/file/upload", image, options);
});
return $q.all(promises).then(lastTask); // returns a promise for results
};
最后,如果该函数应该返回一个promise,那么无论在哪里使用它都要确保添加错误处理(例如在链的末尾加.catch
)。如果这个函数应该是promise链的末尾(例如,只是通过按钮点击触发而没有任何内容正在侦听响应),那么你需要将catch添加到$q.all(promises).then(lastTask)
的末尾。不要发生无声错误。