angularjs - running a "background task" in javascript - Stack Overflow

Is it possible, in Javascript, to run a function in background ?I am generating a pdf with pdfmake tool

Is it possible, in Javascript, to run a function in background ?

I am generating a pdf with pdfmake tool in an angularJS app, but the pdf generation is quite long (3-4 seconds) and during this time, the ui freeze pletely.

I would like to run a background task and force the pdf download without freezing the user ui, is it possible ?

Here how I am running pdfmake (pdfmake and _ are custom factories):

'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'
            }
        }]);

Is it possible, in Javascript, to run a function in background ?

I am generating a pdf with pdfmake tool in an angularJS app, but the pdf generation is quite long (3-4 seconds) and during this time, the ui freeze pletely.

I would like to run a background task and force the pdf download without freezing the user ui, is it possible ?

Here how I am running pdfmake (pdfmake and _ are custom factories):

'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'
            }
        }]);
Share Improve this question edited Mar 26, 2015 at 15:47 kitensei asked Mar 26, 2015 at 15:42 kitenseikitensei 2,5302 gold badges44 silver badges69 bronze badges 3
  • What does create(data).download do? I'm curious if you are using a synchronous call to do this (bad). – KJ Price Commented Mar 26, 2015 at 15:45
  • I am, and I would like to know how to make this async, I'll update the question with the full generation code – kitensei Commented Mar 26, 2015 at 15:46
  • I have updated my question, the create() function is just a wrapper for pdfmake.createPdf() which is synchronous, all my data is already loaded and cached from an ui-grid table – kitensei Commented Mar 26, 2015 at 15:49
Add a ment  | 

1 Answer 1

Reset to default 4

You could use a Web Worker to generate the PDF. But you should be aware of some restrictions when using them. Here is a good reference.

I created a factory in Angular for doing work on a worker thread. Something like this:

/*
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;
    });

This will give you a rough idea about how it can be implemented in AngularJS, but seriously take it with a grain of salt.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745566369a4633418.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信