【问题标题】:Is it feasible to use web worker (multi-threading) in Angular and Typescript in NativeScript?在 Angular 中使用 web worker(多线程)和在 NativeScript 中使用 Typescript 是否可行?
【发布时间】:2017-02-27 14:47:55
【问题描述】:

我目前正在开发一个基于 NativeScript 和 Angular2 的 App。

当我的应用程序通过 HTTP 获取数据时,我的屏幕冻结了一段时间,我想将获取操作放到另一个线程中。

我在网上做了很多搜索,我得到的只是官方文档中的 javascript 代码 - https://docs.nativescript.org/angular/core-concepts/multithreading-model.html

有没有什么方法可以在“Typescript”中使用 WebWorker 实现多线程(其中包含对 Angular 注入 HTTP 服务的支持)而不是“Javascript”代码(来自官方文档的代码)

如果有人能给我一些指导或提示,我将不胜感激,如果我能得到一些相关的示例代码,那就太好了。 谢谢。

【问题讨论】:

  • 在 TypeScript/Angular 中实现 web worker 应该与在 JavaScript 中实现它没有什么不同。现在,您是否应该考虑为 http 使用 webworker 完全是另一个话题。 Http 模块被实现为在另一个线程上工作,因此将其卸载到另一个线程不太可能带来很大的性能提升(如果有的话)。您获取的数据有多大?
  • 感谢您让我知道 HTTP 模块在另一个线程上工作。获取的数据并不是很大(大约 5000 条 XML 格式的记录),然后我认为瓶颈应该是通过 HTTP 获取内容后的 XML 解组。我稍后会尝试看看它是否像我刚才提到的那样。
  • 我发现瓶颈是对 nativescript-sqlite 模块的调用(github.com/NathanaelA/nativescript-sqlite)。所有数据库访问似乎都在导致阻塞的主线程上工作......

标签: javascript angular nativescript


【解决方案1】:

在 {N} + Angular 中使用 WebWorker 应该没有什么大的缺点,但请注意目前 WebWorker 与 Angular AoT 编译不“完全”兼容

对我来说,在将应用程序与 AoT 捆绑后,创建 WebwWrker (var myWorker = new Worker('~/web.worker.js');) 时会抛出错误。我在社区中看到过一些人谈论这个问题,解决这个问题的可能方法是编辑 webpack.common.js 并添加一个“已加载”,如下所示:

{
    test: /\.worker.js$/,
    loaders: [
    "worker-loader"
    ]
}

免责声明:我没有尝试过这种方法来修复错误。

【讨论】:

    【解决方案2】:

    如果有人在使用 Angular 和 Webpack 在 Nativescript 中添加 worker 时遇到问题,您必须按照列出的步骤 here

    在接下来的步骤中要特别小心:

    • 当您导入工作器时,工作器文件的路由位于nativescript-worker-loader! 之后。

    • 在 webpack.config.js 中谨慎添加这段代码:

       {
           test: /.ts$/, exclude: /.worker.ts$/, use: [
               "nativescript-dev-webpack/moduleid-compat-loader",
               "@ngtools/webpack",
           ]
       },
      

    因为很可能你已经配置了AoT编译,像这样:

    {
        test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
        use: [
            "nativescript-dev-webpack/moduleid-compat-loader",
            "@ngtools/webpack",
        ]
    },
    

    您只需要添加exclude: /.worker.ts$/,

    • 最后,有一个worker的例子,在这个例子中它使用了一个Android原生库:

      • example.worker.ts:

         import "globals";
         const context: Worker = self as any;
        
         declare const HPRTAndroidSDK;
        
         context.onmessage = msg => {
             let request = msg.data;
             let port = request.port;
             let result = HPRTAndroidSDK.HPRTPrinterHelper.PortOpen("Bluetooth," + port.portName);
             context.postMessage(result);
         };
        
      • example.component.ts(../../workers/example.worker 是我的 worker 的相对路径):

        import * as PrinterBTWorker from "nativescript-worker-loader!../../workers/example.worker";
        import ...
        
        connect(printer: HPRTPrinter): Observable<boolean> { 
            if (this.isConnected()){
                this.disconnect(); //Disconnect first if it's already connected
            }
            return Observable.create((observer) => {
                const worker = new PrinterBTWorker();
                worker.postMessage({ port: printer });
        
                worker.onmessage = (msg: any)  => {
                    worker.terminate();
                    if (msg.data == 0) { // 0: Connected, -1: Disconnected
                        observer.next(true);
                    }
                    else {
                        observer.next(false);
                    }
                };
        
                worker.onerror = (err) => {
                    worker.terminate();
                    observer.next(false);
                }
            }).pipe(timeout(5000), catchError(err => of(false)));
        }
        

    注意:我使用 Observable 对工作线程进行异步调用,并为对本机代码的调用添加超时,因为在无法连接到打印机的情况下(例如,它已关闭) ),通知需要将近 10 秒,这在我的情况下导致应用程序一直冻结。

    重要提示:似乎每次进行更改时都需要手动再次运行代码,因为worker不是使用AoT编译的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-01
      • 1970-01-01
      • 2016-11-21
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 2019-12-05
      相关资源
      最近更新 更多