AngularJS: status śledzenia każdego przesyłanego pliku jednocześnie
Po naciśnięciu przycisku wysyłania tablica plików ($scope.files
, może być tylko jeden plik, tyle ile chce użytkownik, zostaje przesłany za pośrednictwemFormData
iXMLHttpRequest
w mojej funkcji kątowej$scope.uploadFiles
:
$scope.uploadFiles = function() {
for (var i in $scope.files) {
var form = new FormData();
var xhr = new XMLHttpRequest;
// Additional POST variables required by the API script
form.append('destination', 'workspace://SpacesStore/' + $scope.currentFolderUUID);
form.append('contenttype', 'idocs:document');
form.append('filename', $scope.files[i].name);
form.append('filedata', $scope.files[i]);
form.append('overwrite', false);
xhr.upload.onprogress = function(e) {
// Event listener for when the file is uploading
$scope.$apply(function() {
var percentCompleted;
if (e.lengthComputable) {
percentCompleted = Math.round(e.loaded / e.total * 100);
if (percentCompleted < 1) {
// .uploadStatus will get rendered for the user via the template
$scope.files[i].uploadStatus = 'Uploading...';
} else if (percentCompleted == 100) {
$scope.files[i].uploadStatus = 'Saving...';
} else {
$scope.files[i].uploadStatus = percentCompleted + '%';
}
}
});
};
xhr.upload.onload = function(e) {
// Event listener for when the file completed uploading
$scope.$apply(function() {
$scope.files[i].uploadStatus = 'Uploaded!'
setTimeout(function() {
$scope.$apply(function() {
$scope.files[i].uploadStatus = '';
});
}, 4000);
});
};
xhr.open('POST', '/path/to/upload/script');
xhr.send(form);
}
}
Problemem jestvar i
inkrementuje początkową pętlę for dla każdego pliku, a do czasu wystrzelenia detektorów zdarzeńi
już przekroczył zamierzonefiles[i]
potrzebna wartość, wpływająca tylko na ostatnią w tablicy. używam.uploadStatus
jako środek do interaktywnego pokazywania użytkownikowi postępów poszczególnych plików, dlatego musiałbym mieć osobne detektory zdarzeń dla każdego elementu tablicy w$scope.files
. Jak przypisać i śledzić zdarzenia dla poszczególnych elementów tablicy w Angular?
AKTUALIZACJA
Przerobiłem dwóch słuchaczy zdarzeń, z niewielkim sukcesem, ale wciąż doświadczam dziwnego zachowania:
xhr.upload.onprogress = (function(file) {
// Event listener for while the file is uploading
return function(e) {
$scope.$apply(function() {
var percentCompleted = Math.round(e.loaded / e.total * 100);
if (percentCompleted < 1) {
file.uploadStatus = 'Uploading...';
} else if (percentCompleted == 100) {
file.uploadStatus = 'Saving...';
} else {
file.uploadStatus = percentCompleted + '%';
}
});
}
})($scope.files[i]);
xhr.upload.onload = (function(file, index) {
// Event listener for when the file completed uploading
return function(e) {
$scope.$apply(function() {
file.uploadStatus = 'Uploaded!'
setTimeout(function() {
$scope.$apply(function() {
$scope.files.splice(index,1);
});
}, 2000);
});
}
})($scope.files[i], i);
.onprogress
Wydaje się, że idzie bez problemu, ale z niewielkimi zmianami.onload
, Widzę teraz wiele dziwnych zachowań z dwukierunkowym powiązaniem AngularJS dla jego szablonów. dla każdego elementu w szyku$scope.files
podany jest status przy użyciu powyższego.uploadStatus
własność. Teraz mamsetTimeout
łącz elementy z tablicy, poprzezi
zmienna, która jest przekazywana do funkcji samoczynnie wykonującej. Dziwne, że przesyłanie jest ograniczone do około 6 jednoczesnych wysyłek w danym momencie, co musi być problemem po stronie serwera, ale zauważam, że w miarę łączenia elementów tablicyng-repeat
w szablonie działa dziwacznie tam, gdzie się splotniena element, niekoniecznie te, które powinien. Zauważyłem również, że często są wpisy, które nie są łączone po osiągnięciu progu 2000 milisekund.
Przypomina to oryginalny problem, w którym zmiennai
jest niewiarygodny, gdy jest używany podczas wyzwalania detektorów zdarzeń? Teraz przekazuję to anonimowemu samoczynnemu wykonywaniu.onload
funkcja, a połączenie używa jej do określenia, który element tablicy powinien usunąć, ale niekoniecznie usuwa poprawny i często pozostawia inne elementy w tablicy, gdy powinien je usunąć.