【发布时间】:2019-11-29 16:26:13
【问题描述】:
在我要迁移到 Angular 8 的以前的 AngularJS 应用程序中,我有一个函数,它可以通过绑定函数并将它们放在一个数组中来下载函数,等待使用 reduce 函数调用。例如:
function stageForDownload() {
$scope.files.forEach(function (file) {
if (file.checked) {
$scope.downloadFunctions.push(downloadFile.bind(null, file));
}
});
}
function downloadStaged() {
$scope.downloadFunctions.reduce(
function (prev, next) {
return prev.then(next);
}, Promise.resolve())
.then( /* do something now that all files are downloaded */ );
}
}
这段代码基本上会以一种一种方式解决promise,直到函数列表为空。与 Angular 8 一样,promise 的结构以不同的方式工作(这意味着它们现在使用 ECMA 6 实现),我不确定如何迁移此代码。让我更加困惑的是, HttpClient 角度提供的现在返回一个可以订阅的 Observable;虽然 rsjx 的 forkJoin() 方法似乎完全支持我想要做的事情,但它不会接受绑定函数列表。
我只需要知道所有功能何时完成,因为它们是运行导出服务方法来下载文件的空白。所以我不一定需要从这些正在减少的方法中返回/订阅任何数据。
编辑:
还有两个我忘了提及的功能。这里是downloadFile,负责调用exportService。
function downloadFile(file) {
var deferred = $q.defer();
$scope.date = formatDate($scope.datepicker.selectedDate);
$scope.fileDate = dateToYMD($scope.datepicker.selectedDate);
exportService.exportData(file.FileNamePrefix + " " + $scope.fileDate + ".xlsx", 'SOME_API_LOCATION' + $scope.date, file).then(
function () {
deferred.resolve();
},
function (error) {
deferred.reject();
notificationService.displayError("Internal Error!");
});
return deferred.promise;
}
这里是 exportService 本身:
(function (app) {
'uuse strict';
app.factory('exportService', exportService);
exportService.$inject = ['$q', '$http'];
function exportService($q, $http) {
var service = {
exportData: exportData,
createFilename: createFilename
};
function exportData(filename, url, data) {
var config = {
responseType: 'arraybuffer'
};
return $http.post(url, data, config).then(
function (response) {
var deferred = $q.defer();
var data = response.data;
var status = response.status;
var headers = response.headers();
var octetStreamMime = 'application/octet-stream';
var success = false;
var contentType = headers['content-type'] || octetStreamMime;
try {
// Try using msSaveBlob if supported
var blob = new Blob([data], { type: contentType });
if (navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if (saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
success = true;
deferred.resolve();
} catch (ex) {
}
if (!success) {
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if (urlCreator) {
// Try to use a download link
var link = document.createElement('a');
if ('download' in link) {
// Try to simulate a click
try {
// Prepare a blob URL
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
success = true;
deferred.resolve();
} catch (ex) {
}
}
if (!success) {
// Fallback to window.location method
try {
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
success = true;
deferred.resolve();
} catch (ex) {
deferred.reject();
}
}
}
}
return deferred.promise;
},
function (error) {
return $q.reject(error);
});
}
}
})(angular.module('app'));
所以看来我的问题不一定是触发一个动态创建的 http 请求列表,而是如何使用 $q 将承诺转换为 ECMA6+ 承诺。
【问题讨论】:
-
angular http.get 返回一个你可以调用
.toPromise()的可观察对象,你可以将它放入一个数组中。然后您可以拨打Promise.all()。触发并等待完成 -
我在 OP 中添加了更多信息。我相信 exportService 仍然可以使用 subscribe 来处理 http 请求,但是我应该为将 arraybuffer 下载为 xlsx 文件的逻辑做出新的承诺,对吗?
标签: javascript angularjs angular migration angular8