angular-file-upload angularjs 中的异步过滤器

angular-file-upload async filter in angularjs

我正在使用 angular-file-upload 上传文件,我正在编写一个过滤器,我需要在其中 csv 文件选择上传并将它们与 API 中的 headers 匹配。我能够从 csv 和 API 中获取 headers 并比较它们,但上传器回调函数(如 uploader.onWhenAddingFileFailed(), uploader.onAfterAddingFile())不会等待我的过滤器执行,它们会异步执行。

因此,上传器回调函数应该等到我的过滤器函数执行,然后,取决于响应 (true/false)将采取进一步行动。

我当前的过滤器代码是 -

uploader.filters.push({
    name: 'fileTemplateFilter',
    fn: function(item /*{File|FileLikeObject}*/ , options, deferred) {

        var getCsvHeaders = function() {
            // $http.post(csvHeadersUrl + vm.vendorWithSearchItem.selected.vendorid + '&fileName=' + item.name)
            return $http.get('app/pages/utilities/inventoryMapper/csvHeader.csv')
                .then(function(success) {
                    vm.tableHeaders = success.data;
                    return true;
                }, function(error) {
                    vm.tableHeaders = undefined;
                    return false;
                }).catch(function(e){
                    return false;
                });
        }

        var getFileHeaders = function() {
            var r = new FileReader();
            r.onload = function(e) {
                var contents = e.target.result;
                contents = contents.split(/\r\n|\n/);
                var i = 0,
                    flag = false,
                    headers;
                while (i < contents.length && flag == false) {
                    if (contents[i] != '') {
                        headers = contents[i]
                        flag = true;
                    }
                    i++;
                }
                vm.fileHeaders = headers.split(",").map(function(item) { return item.trim() && item.replace(/['"]+/g, ''); });
                return true;
            };
            r.readAsText(item);
            return false;
        }

        var isTemplateSame = function() {
            return Promise.all([getCsvHeaders(), getFileHeaders()]).then(function() {
                if(vm.fileHeaders && vm.tableHeaders) {
                    var is_same = (vm.fileHeaders.length == vm.tableHeaders.length) && vm.fileHeaders.every(function(element, index) {
                        return element === vm.tableHeaders[index];
                    });
                    return is_same == true ? true : false;
                }
            })
        }

        return Promise.resolve(isTemplateSame()).then(function(value) {
            return value;
        });
        // setTimeout(deferred.resolve, 1e3);
    }
});

Here, I need following -

1) my filter reads whole csv & then returns headers; Please suggest code improvements so that only headers will be read instead of whole file.

2) The correct implementation of promise in this filter

I got the solution for the promise implementation. I used deferred promise & it worked for me. And at this time, also found quick parser - PapaParse for csv parsing.

所以,我更新后的过滤器如下 -

uploader.filters.push({
    name: 'fileTemplateFilter',
    fn: function(item /*{File|FileLikeObject}*/ , options, deferred) {
        vm.tableHeaders = undefined;
        vm.fileHeaders = undefined;
        var getCsvHeaders = function() {
            // return $http.get('app/pages/utilities/inventoryMapper/csvHeader.csv')
            return $http.post(csvHeadersUrl + vm.vendorWithSearchItem.selected.vendorid + '&fileName=' + item.name)
                .then(function(success) {
                    vm.tableHeaders = success.data;
                    return vm.tableHeaders;
                }, function(error) {
                    vm.tableHeaders = undefined;
                    throw error.status + " : " + error.data;
                }).catch(function(e){
                    return false;
                });
        }

        var getFileHeaders = function() {
            var defer = $q.defer();
            Papa.parse(item, {
                worker: true,
                skipEmptyLines: true,
                step: function(results, parser) {
                    parser.abort();
                    vm.fileHeaders = results.data[0] || undefined;
                    results = null;
                    defer.resolve(vm.fileHeaders);
                },
                complete: function(results){
                    results = null;
                }
            });
            return defer.promise;
        }

        $q.all([getCsvHeaders(), getFileHeaders()]).then(function() {
            if(vm.fileHeaders && vm.tableHeaders) {
                var is_same = (vm.fileHeaders.length == vm.tableHeaders.length) && vm.fileHeaders.every(function(element, index) {
                    return element === vm.tableHeaders[index];
                });
                if(is_same == true) {
                    deferred.resolve(is_same);
                } else {
                    toastr.error('file template doesn\'t match for this file - ' + item.name + ' ...!', 'Error');
                    deferred.reject(false);
                }
            } else {
                deferred.reject(false);
            }
        }, function(error) {
            deferred.reject(error);
        })

        return deferred.promise;
    }
});