8.4 Job and Job Queues
Job是一个抽象操作,就是一个当没有其他ECMAScript计算正在进行的时候启动的一个ECMAScript计算。一个JOb抽象操作一般会被定义为可以接受任意个Job参数。
只有当execution context stack 为空并且没有running execution context 时,才可能启动执行Job。一个PendingJob时一个要求在未来执行的Job,它在内部是Record,其字段定义在Table 25 中。一旦Job启动执行,一定会执行完成,在这期间不会有其他的Job启动。然而,当前值执行的Job或者外部的事件可能会加入额外的PendingJobs,他们会在执行完当前的Job后的某个时机启动执行。
表 25 PendingJob Record Fields
字段名 | 值 | 意义 |
---|---|---|
[[Job]] | Job抽象操作的名字 | 这就是当PendingJob启动的时候会执行的抽象操作,Jobs是抽象操作,他们使用NextJob 而不是平常那样,返回一个值,告诉你他们已经完成了。 |
[[Arguments]] | 一个List | 一组参数,当[[Job]]被激活的时候,会传个[[Job]] |
[[Realm]] | 一个Realm Record | 用来启动执行上下文,当启动PendingJob的时候 |
[[ScriptOrModule]] | 一个Script Record或者Module Record | 用来启动执行上下文,当启动PendingJob的时候 |
[[HostDefined]] | 任意值,默认是undefined | 保留的一些宿主环境需要使用的字段,为了给pending Job附加额外信息。 |
Job队列是一个先进先出的PendingJob的队列,每个Job队列都有一个名字,并且全部可用的Job队列由ECMAScript实现定义。每种实现都至少会有表26中的Job队列。
表 26 必须的Job队列
名字 | 目的 |
---|---|
ScriptJobs | 验证并且执行ECMAScript 脚本或者Module源代码的Job,如第10章和第15章 |
PromiseJobs | 响应一个已经settle的Promiser(见25.4章) |
一个要在未来执行的Job是靠入列来实现的,在一个Job队列中,一个PendingJob record包含一个Job抽象操作名和必须的参数值。当execution context stack 为空并且没有running execution context 时,ECMAScript实现会从一个Job队列中移除第一个PendingJob,然后使用其中包含的信息来创建一个执行上下文,并且开始执行这个关联的Job抽象操作。
PendingJob在一个单一队列中,总是先进先出的顺序,这个规范并没有定义多个队列之间的服务顺序。一个ECMAScript实现可能会交织着在多个任务队列之间切换。一个ECMAScript实现必须定义当execution context stack 为空并且没有running execution context 时会发生什么。
注意:典型的ECMAScript实现会有预先启动的Job队列,并且最少有一个Job队列,并且其中会有一个Job被第一个执行。一个实现可能会选择在当前Job执行完并且Job队列是空的时候释放所有资源并且终止执行。另一种情况是,它会选择等待特殊定义实现的代理或者机制确保会把一个新的PendingJob入列。
下面抽象操作是用来创建和管理Job和Job队列的:
8.3.1 EnqueueJob (queueName,job,arguments)
这个 抽象操作要求三个参数,queueName,Job,arguments,执行过程如下:
- Assert: Type(queueName) is String and its value is the name of a Job Queue recognized by this implementation.
- Assert: job is the name of a Job.
- Assert: arguments is a List that has the same number of elements as the number of parameters required by job.
- Let callerContext be the running execution context.
- Let callerRealm be callerContext's Realm.
- Let callerScriptOrModule be callerContext's ScriptOrModule.
- Let pending be PendingJob{ [[Job]]: job, [[Arguments]]: arguments, [[Realm]]: callerRealm, [[ScriptOrModule]]: callerScriptOrModule, [[HostDefined]]: undefined }.
- Perform any implementation or host environment defined processing of pending. This may include modifying the [[HostDefined]] field or any other field of pending.
- Add pending at the back of the Job Queue named by queueName.
- Return NormalCompletion(empty).
8.3.2 NextJob
如果算法步骤是如下:
- NextJob result
使用如下操作替换:
- Return result
Job的抽象操作必须包含一个返回操作或者ReturnIfAbrupt,NextJob result操作和如下步骤是一样的:
- If result is an abrupt completion, perform HostReportErrors(« result.[[Value]] »).
- Suspend the running execution context and remove it from the execution context stack.
- Assert: The execution context stack is now empty.
- Let nextQueue be a non-empty Job Queue chosen in an implementation defined manner. If all Job Queues are empty, the result is implementation defined.
- Let nextPending be the PendingJob record at the front of nextQueue. Remove that record from nextQueue.
- Let newContext be a new execution context.
- Set newContext's Function to null.
- Set newContext's Realm to nextPending.[[Realm]].
- Set newContext's ScriptOrModule to nextPending.[[ScriptOrModule]].
- Push newContext onto the execution context stack; newContext is now the running execution context.
- Perform any implementation or host environment defined job initialization using nextPending.
- Perform the abstract operation named by nextPending.[[Job]] using the elements of nextPending.[[Arguments]] as its arguments.