首先,如果你不熟悉这个项目,建议先阅读之前写的一系列文章。如果你不想阅读这些,不用担心。这里面也会涉及到那些内容。
现在,让我们开始吧。
去年,我开始实现Nexus.js,这是一个基于Webkit/JavaScript内核的多线程服务端JavaScript运行库。有一段时间我放弃了做这件事,由于一些我无法控制的原因,我不打算在这里讨论,主要是:我无法让自己长时间工作。
所以,让我们从讨论Nexus的架构开始,以及它是如何工作的。
事件循环
没有事件循环
有一个带有(无锁)任务对象的线程池
每次调用setTimeout或setImmediate或创建一个Promise时,任务就排队到任务队列钟。
每当计划任务时,第一个可用的线程将选择任务并执行它。
在CPU内核上处理Promise。对Promise.all()的调用将并行的解决Promise。
ES6
支持async/await,并且推荐使用
支持for await(...)
支持解构
支持async try/catch/finally
模块
不支持CommonJS。(require(...)和module.exports)
所有模块使用ES6的import/export语法
支持动态导入通过import('file-or-packge').then(...)
支持import.meta,例如:import.meta.filename以及import.meta.dirname等等
附加功能:支持直接从URL中导入,例如:
import { h } from 'https://unpkg.com/preact/dist/preact.esm.js';
EventEmitter
Nexus实现了基于Promise的EventEmitter类
事件处理程序在所有线程上排序,并将并行处理执行。
EventEmitter.emit(...)的返回值是一个Promise,它可以被解析为在事件处理器中返回值所构成的数组。
例如:
class EmitterTest extends Nexus.EventEmitter { constructor() { super(); for(let i = 0; i < 4; i++) this.on('test', value => { console.log(`fired test ${i}!`); console.inspect(value); }); for(let i = 0; i < 4; i++) this.on('returns-a-value', v => `${v + i}`); } } const test = new EmitterTest(); async function start() { await test.emit('test', { payload: 'test 1' }); console.log('first test done!'); await test.emit('test', { payload: 'test 2' }); console.log('second test done!'); const values = await test.emit('returns-a-value', 10); console.log('third test done, returned values are:'); console.inspect(values); } start().catch(console.error);
I/O
所有输入/输出都通过三个原语完成:Device,Filter和Stream。