🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# [**多线程模式**](http://docs.nativescript.org/core-concepts/multithreading-model#multithreading-model) NativeScript的好处之一就是它允许通过JS快速高效地使用所有原生平台( Android\/Objective-C )的API,而不用使用串行化或者映射。然而这导致另一个纠结——所有JS都在主线程上执行 \(又名: `UI thread`\) 。这意味着操作很可能花掉很多时间停滞于UI渲染并且让应用看起来感觉很慢。 要解决UI的清晰度和高性能带来的缓慢是至关重要的,开发者可以使用 NativeScript的解决方案处理多线程——工作者线程。工作者是在一个绝对隔离的上下文中在后台线程上执行的脚本。要花掉很多时间执行的任务应该卸装到一个工作者线程之上。 NativeScript 里的 Workers API 是松散地基于 [Dedicated Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) 和 [Web Workers Specification](https://www.w3.org/TR/workers/) 。 * [Workers API](http://docs.nativescript.org/core-concepts/multithreading-model#workers-api) * [Worker Object](http://docs.nativescript.org/core-concepts/multithreading-model#worker-object-prototype) * [Worker Global Scope](http://docs.nativescript.org/core-concepts/multithreading-model#worker-global-scope) * [Sample Usage](http://docs.nativescript.org/core-concepts/multithreading-model#sample-usage) * [Limitations](http://docs.nativescript.org/core-concepts/multithreading-model#limitations) ## [**Workers API**](http://docs.nativescript.org/core-concepts/multithreading-model#workers-api) ### **[Worker 对象原型](http://docs.nativescript.org/core-concepts/multithreading-model#worker-object-prototype)** * `new Worker(path)` - 创建一个worker的一个实例,并生成一个操作系统的新线程,该脚本的指向由执行的 `path` 参数决定。 * `postMessage(message)` - 发送一个串行化的JSON消息关联脚本的 `onmessage` 事件处理器。 * `terminate()` - 终止运行下一个运行循环上的worker线程。 **Worker** 对象事件处理器 * `onmessage(message)` - 处理发送自关联的worker线程传入的消息。消息对象有如下属性: * `message.data` - 消息内容, 如在worker线程发送的 `postMessage` 。 * `onerror(error)` - 处理从worker线程未捕获的错误。. 错误对象暴露如下属性: * `error.message` - 未发现的错误,一个堆栈,如果可用的话。 * `error.filename` - 文件位置,如果抛出未捕获错误的话。 `error.lineno` - 行号,如果抛出未捕获错误的话。 ### **[Worker 全局范围 ](http://docs.nativescript.org/core-concepts/multithreading-model#worker-global-scope)** * `self` - 返回 `WorkerGlobalScope` 本身的一个引用。 * `postMessage(message)` - 发送一个串行化的JSON消息到主线程上的Worker 实例的 `onmessage` 事件处理器。 * `close()` - 终止运行下一个运行循环上的worker线程。 **Worker 全局范围事件处理器** * `onmessage(message)` - 处理发送自主r线程传入的消息。消息对象暴露如下属性: * `message.data` - 消息内容, 如在主r线程发送的 `postMessage` 。 * `onerror(error)` - 处理 Worker 作用域(worker线程)内部执行的函数未捕获的错误 。 `error` 参数包含未捕获的错误。如果处理器返回一个真类的值,消息不会传播到主线程上的 Worker 实例的 `onerror` 处理器。`onerror` 调用 worker 线程之后,执行不会被终止,worker仍然能够发送\/接收消息。 * `onclose()` - 处理任何“清理”工作;适用于释放资源,关闭流和套接字。 ![](/assets/Workers1.png) > **main-view-model.js ** > > --- > > `...` > > `var worker = new Worker('./workers/image-processor');` > > `worker.postMessage({ src: imageSource, mode: 'scale', options: options });` > > `worker.onmessage = function(msg) {` > > `if (msg.data.success) {` > > `// Stop idle animation` > > `// Update Image View` > > `// Terminate worker or send another message` > > `worker.terminate();` > > `} else {` > > `// Stop idle animation` > > `// Display meaningful message` > > `// Terminate worker or send message with different parameters` > > `}` > > `}` > > `worker.onerror = function(err) {` > > ``console.log(`An unhandled error occurred in worker: ${err.filename}, line: ${err.lineno} :`);`` > > `console.log(err.message);` > > `}` > > `...` > > **workers\/image-processor.js ** > > --- > > `onmessage = function(msg) {` > > `var request = msg.data;` > > `var src = request.src;` > > `var mode = request.mode || 'noop' ;` > > `var options = request.options;` > > `var result = processImage(src, mode, options);` > > `var msg = result !== undefined ? { success: true, src: result } : { }` > > `postMessage(msg);` > > `}` > > `function processImage(src, mode, options) {` > > `// image processing logic` > > `// save image, retrieve location` > > `// return source to processed image` > > `return updatedImgSrc;` > > `}` > > ``// does not handle errors with an `onerror` handler`` > > `// errors will propagate directly to the main thread Worker instance` ## [**General Guidelines**](http://docs.nativescript.org/core-concepts/multithreading-model#general-guidelines)通用指导原则 为了最理想的结果,当使用 Workers API 时,请遵循这些准则: * 当 worker结束任务时,使用适合的API \(`terminate()` 或`close()`\) ,始终要确保关闭 worker 线程。如果在你工作的作用域之内,你的 Worker 实例在你能终止它之前变得不能得到,你要关闭它,就只能在worker自身的脚本里通过调用 `close()` 函数。 * Workers 不是所有性能相关问题的通用解决方案。 开启一个Worker 有它自身的开销, 而且它可能有时会比处理一个快速任务更慢。所以,在诉诸worker之前优化数据库请求,或重新考虑复杂应用逻辑。 * 线程可以访问整个原生SDK, 当 调用API时 ,nativescript 开发者必须照顾到所有的同步,这些从多个线程的调用无法保证线程安全。 ## **[Limitations限制](http://docs.nativescript.org/core-concepts/multithreading-model#limitations)** 当使用 worker时有一些限制要记住: * 不存在JS共享内存。这意味着你不能从任一线程获得JS的值\/对象。你只能串行化对象,把它发送到另一个线程并在那里反串行化。这就是 postMessage\(\) 函数所负责的。然而,原生对象没有这个情况。你可以从多个线程获取一个原生对象,而不用复制它,因为 runtime 将创建每个线程单独的JavaScript包装对象。请记住,当您使用非线程安全的原生API和数据时,你必须自己处理同步部分。 runtime 在原生数据访问和API调用上,不执行任何锁定或者同步逻辑。 * 只有串行化JSON 对象可以被 postMessage\(\) API 发送。 * 你不能发送原生对象。意思是你不能通过 postMessage 发送原生对象,因为在大多数情况下,JSON序列化JavaScript包装一个原生对象的结果为空的-“{ }” 字面的对象。另一方面这个消息会被反序列化到一个纯粹的空的JavaScript对象。发送原生对象是我们希望在未来支持的,所以敬请关注。 * 此外,当发送循环对象时要小心,因为它们的递归节点将在序列化步骤中剥离。 * 没有对象传输。如果你是一个Web开发者你可能熟悉ArrayBuffer和MessagePort的传输在浏览器被支持。目前, NativeScript 没有这种对象传输的概念。 * 目前,你无法调试运行在worker线程的上下文中的脚本。以后会实现。 * 没有嵌套的worker支持。我们希望从社区获知如果这在一定程度上需要我们支持的话。