在Javascript中,是否可以在后台运行函数?
我在angularJS应用程序中使用pdfmake工具生成pdf,但pdf生成时间很长(3-4秒),在此期间,ui完全冻结。
我想运行一个后台任务并强制下载而不冻结用户ui,是否可能?
我在这里运行pdfmake(pdfmake
和_
是自定义工厂):
'use strict';
angular.module('App')
.service('CatalogPdfService', ['pdfmake', '_', '$q', '$filter',
function (pdfmake, _, $q, $filter) {
var $translate = $filter('translate');
var listDate = new Date();
return {
download: download
};
function download(data) {
listDate = _.first(data).publishedOn;
console.log('start download');
var deferred = $q.defer();
var filename = $translate('APP.EXPORT.pdf.catalog.title', {date: $filter('amDateFormat')(listDate, 'DDMMYYYY')}) + '.pdf';
create(data).download(filename, function () {
console.log('end download');
deferred.resolve();
});
return deferred.promise;
}
function create(data) {
// group data by category
var dataByCategory = _.groupBy(data, function (d) {
return d.category;
});
// group categories data by subcategory
_.forEach(dataByCategory, function (d, i) {
dataByCategory[i] = _.groupBy(d, function (d) {
return d.subcategory;
});
});
var content = {
table: {
headerRows: 1,
widths: ['*', 20, 10, 20, 20, 20, 20, 40, 20, 30],
body: [
[
{text: $translate('APP.EXPORT.pdf.catalog.header.article') , style: 'headings', alignment: 'left'},
{text: $translate('APP.EXPORT.pdf.catalog.header.mine') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.rank') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.origin') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.transporter') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.culture') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.label') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.unit') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.packing') , style: 'headings'},
{text: $translate('APP.EXPORT.pdf.catalog.header.price') , style: 'headings'}
]
]
},
layout: {
hLineWidth: function (i) {
return (i == 0) ? 0 : 1;
},
vLineWidth: function (i) {
return 0;
},
hLineColor: function (i, node) {
return '#ccc';
}
}
};
_.forEach(dataByCategory, function (data, category) {
content.table.body = content.table.body.concat(renderCategory(category, data));
});
var dd = {};
dd.content = renderHeader().concat(content);
dd.header = function (currentPage, pageCount) {
return {
text: $translate('APP.EXPORT.pdf.catalog.pagecount', {start: currentPage.toString(), end: pageCount.toString()}),
alignment: 'right',
color: '#666',
margin: [0, 20, 40, 0]
};
};
dd.styles = {
title: {
fontSize: 15,
bold: true
},
headings: {
italics: true,
alignment: 'center'
},
flag: {
alignment: 'center',
italics: true,
color: '#666'
},
category: {
bold: true,
fontSize: 12,
margin: [0, 10, 0, 0] // Left, Top, Right, Bottom
},
subcategory: {
bold: true,
fontSize: 10,
margin: [0, 7, 0, 5] // Left, Top, Right, Bottom
}
};
dd.defaultStyle = {
fontSize: 8
};
return pdfmake.createPdf(dd);
}
function renderHeader() {
return [
{image: logo(), height:40, width: 86},
{
margin: [0, 10, 0, 20],
table: {
widths: [100, 100, 100, '*'],
body: [
[
{text: $translate('APP.COMMON.address', {char: '\n'})},
{text: '\n' + $translate('APP.COMMON.phone')},
{text: '\n' + $translate('APP.COMMON.fax')},
{text: '\n' + $translate('APP.EXPORT.pdf.catalog.listno', {date: $filter('amDateFormat')(listDate, 'DD/MM/YYYY')}) , alignment: 'right'}
]
]
},
layout: {
hLineWidth: function (i) {
return (i == 0) ? 0 : 1;
},
vLineWidth: function (i) {
return 0;
}
}
}];
}
function renderCategory(name, data) {
var category = [
[
{text: name, style: 'category', colspan: 10},
'', '', '', '', '', '', '', '', ''
]
];
_.forEach(data, function (data, name) {
category = category.concat(renderSubcategory(name, data));
});
return category;
}
function renderSubcategory(name, data) {
var subcategory = [
[
{text: name, style: 'subcategory', colspan: 10},
'', '', '', '', '', '', '', '', ''
]
];
_.forEach(data, function (product) {
subcategory.push(renderProduct(product));
});
return subcategory;
}
function renderProduct(product) {
return [
product.name,
{
text: (product.isInPrivateList ? 'Oui' : ''),
style: 'flag'
},
{
text: (null === product.rank ? '' : String(product.rank)),
style: 'flag'
},
{
text: (product.origin || ''),
style: 'flag'
},
{
text: (product.transporter || ''),
style: 'flag'
},
{
text: (product.label || ''),
style: 'flag'
},
{
text: (product.culture || ''),
style: 'flag'
},
{
text: product.unit,
margin: [0, 0, 5, 0],
italics: true,
alignment: 'right'
},
{
text: (product.quantity || '1'),
italics: true,
fillColor: '#eee',
alignment: 'center'
},
{
text: product.unitPrice,
margin: [0, 0, 5, 0],
italics: true,
fillColor: '#eee',
alignment: 'right'
}
];
}
function logo() {
return 'data:image/jpeg;base64,blabla bigbase64 string'
}
}]);
答案 0 :(得分:5)
您可以使用Web Worker生成PDF。但是在使用它们时应该注意一些限制。 Here是一个很好的参考。
我在Angular中创建了一个工厂,用于处理工作线程。像这样:
/*
Here's an example on how to get this sack of moldering spuds to do something:
var myWorker = new MyWorker({ fn: function() {
this.onmessage = function(args) {
setTimeout(function() {
this.postMessage('Got args: ' + args.data);
}, 20000);
};
} });
myWorker.do('Test').then(function(message) {
alert(message);
});
*/
'use strict';
angular.module('myApp')
.factory('MyWorker', function($q) {
var _worker;
var MyWorker = function(settings) {
_init(settings);
};
MyWorker.prototype.do = function(args) {
var deferred = $q.defer();
_worker.onmessage = function(message) {
deferred.resolve(message.data);
};
//Fire up the blades.
if (args)
_worker.postMessage(args);
else
_worker.postMessage();
return deferred.promise;
};
MyWorker.prototype.destroy = function() {
_worker.terminate();
};
function _init(settings) {
if (settings.script)
_worker = new Worker(settings.script);
//Need to make this IE (10+) friendly.
else if (settings.fn) {
var blobUrl = window.URL.createObjectURL(new Blob(
['(', settings.fn.toString(), ')()'],
{ type: 'application/javascript' }
));
_worker = new Worker(blobUrl);
}
};
return MyWorker;
});
这将让您大致了解如何在AngularJS中实现它,但是要认真对待它。