# 使用 NativeScript 将任务卸载到辅助线程
性能。性能。性能。
当我们与 NativeScript 开发人员交谈时,性能始终是他们选择 NativeScript 的首要原因之一。这也是我们永远无法获得的。在移动硬件不断改进的同时,总有方法可以改善我们创建的应用程序的性能,从而改善用户体验。
除了在 iOS 和 Android 上提供真正的本机 UI 外,NativeScript 还具有一些其他技巧,使您可以针对独特的场景自定义应用程序,并从宝贵的 CPU 周期中挤出更多资源。
让我向您介绍 NativeScript 上的工作线程。
# 工作线程
在 Web 世界中被称为 Web Worker(或 Service Worker),Worker 线程使您可以采用 NativeScript 提供的单线程环境并将其转变为多线程环境。
TIP
注意: NativeScript 中的 Workers API 大致基于 Web Workers API 和 Web Workers Specification。
服务工作者(一种网络工作者)在渐进式 Web 应用程序(PWA)开发人员中很受欢迎,因为它们允许进行通知和其他非阻塞任务。但是在 PWA 功能结束的地方,NativeScript 弥补了这一不足。
正如此 NativeScript 演示应用程序所证明的那样,单线程模型在 99%的时间内都很好(因为在 UI 线程上运行所有内容都非常快):
nativescript 演示应用
但是,在某些情况下,操作可能需要更长的时间,从而影响应用程序的 UI。这可能会导致应用感觉比预期的慢。
为了解决此问题,NativeScript 提供了一个 Workers API,该 API 可让您创建在独立于主应用程序上下文的独立线程上执行的任务。
让我们看一下何时(以及何时不)在 NativeScript 应用程序中使用 worker 的一些示例。
# 何时使用工人
实际上,至少在理论上,可以在同步 UI 操作之外运行的任何任务都是工作线程的候选对象。
TIP
提示:在您开始认为工作线程是解决复杂性能问题的灵丹妙药之前,请确保考虑到增加其他线程所需的开销。
CPU 密集型,与 UI 不相关的任务可能是使工作线程受益的最佳示例。如果您是 Google Analytics(分析)的重度用户,则可能会发现自己正在评估应用程序中的每个用户操作,页面视图,功能使用和远程服务调用。即使这些调用应该异步运行,它们仍然会对主线程产生负面影响。
另一个很好的例子是图像处理-单独执行 CPU 密集型任务,将其混合到 UI 线程中会变得更加复杂!
TIP
这些用于 NativeScript Core 和 Angular 的演示应用程序中提供了卸载图像处理的绝佳示例。
# 样例代码
让我们看看我们如何自己构建一个非常简单的工人:
var worker = new Worker('./workers/my-worker.js');
上面的代码启动一个新线程(运行时实例)并执行引用的脚本(my-worker.js
)。接下来,我们将要与工作 人员进行通信和/或从中接收消息或结果。这是通过以下消息完成的:
// send a message to our worker
worker.postMessage('Hello worker thread!');
// receive a message from our worker
worker.onmessage = function(msg) {
console.log('Received this message from the worker thread: ' + msg.data);
};
在我们的my-worker.js
文件中,我们将提供从主线程接收消息的onmessage
方法:
onmessage = function(msg) {
console.log('Received this message from the main thread: ' + msg.data);
// perform some crazy cpu-intensive task here!
// send a message back to the main thread
postMessage('Hello main thread!');
close();
};
# 错误处理和终止线程
使用工作线程可能会有些吓人,因为打开的线程可能会消耗资源,并可能占用大量内存并破坏性能。因此,请确保您捕获任何错误并在完成后关闭/终止线程:
中的基本示例my-worker.js
:
onerror = function(e) {
console.log('Oh no! Worker thread error: ' + e);
return true;
};
并在您的应用代码中(您想显示一个错误):
worker.onerror = function(e) {
console.log('Worker thread error: ' + e);
};
TIP
重要说明:辅助线程一直处于活动状态,直到被主线程明确终止或自行关闭为止!
关闭线程在my-worker.js
与close();
(如上图所示)。或使用终止应用程序代码中的线程worker.terminate();
。
如果工作线程未终止/关闭,则垃圾收集器将不会收集和处理工作实例。
# 什么时候不雇用工人
重要的是要记住,每次启动新的辅助线程时,都会增加应用程序的资源和内存占用量。这意味着如果您一次旋转太多或在错误的情况下使用它们,则应用程序的性能实际上可能会下降。
如果您认为辅助线程可以帮助您处理来自表单的输入,显示图表或许多其他基本应用程序功能,请三思。NativeScript 框架已针对大多数此类方案进行了优化。
最好的选择是始终在开发过程中评估您的应用在各种 iOS 和 Android 物理设备上的功能性能!
话虽如此,在缺乏主线程性能的边缘情况下,工作者可能会超级有用。您要做的最好的事情就是测试各个方案,并衡量哪种方案最适合您的情况。