Javascript Promises库在浏览器中制作“长时间运行代码 - 非阻塞UI”?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript Promises库在浏览器中制作“长时间运行代码 - 非阻塞UI”?相关的知识,希望对你有一定的参考价值。

更新

这是对下面问题的更新,应该有助于找到答案

接受torazaburo的答案,Promise/A+也引用了部分杰出的javascript Promise / A +定义,我想在此更新问题。 onFulfilled规范在第2.2.4点建议:

在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilled或onRejected。 3.1。

并进一步解释

这里的“平台代码”意味着引擎,环境和承诺实现代码。实际上,这个要求确保onFulfilled和onRejected异步执行,然后调用事件循环,然后调用新堆栈。这可以使用诸如setTimeout或setImmediate之类的“宏任务”机制,或者使用诸如MutationObserver或process.nextTick之类的“微任务”机制来实现。由于promise实现被认为是平台代码,因此它本身可能包含一个任务调度队列或“trampoline”,其中调用处理程序。

我期待在这个问题中找到的这个问题是,关键是Promise实现Javascript代码本身被认为是平台代码,并且允许不通过调用onRejected onFulfilled函数来解决后续promise之间的eventloop。这在Node.js(服务器)中是很好的,因为它避免了回到事件循环(离开执行堆栈)的不必要的回归,但也导致浏览器中的挑战,因为执行堆栈没有退出,在解决潜在的大承诺的数量(它们本身可以产生新的承诺)。不离开执行堆栈并屈服于事件循环会导致浏览器出现意外(阻塞脚本警告/问题)。然而,导致这种需要的Promise实现的“trampoline”任务调度不必避免不时地将执行交还给Javascript事件循环。这样的功能允许将Promise用于较重的任务。在这个问题中搜索/要求这种“长期运行代码”的Promises实现。

澄清:“过长”不是onFulfilled函数的个体长度,而是由于Promise解析过程(当以这样的“蹦床”方式完成时)将几个函数/回调连接在一起。我已经意识到,如果一个人的Promises函数太长,那么使用任何类型的Promise实现都无法以任何方式帮助它。

这里的交易是x promises的后续解析(在一个执行堆栈内,因此没有回到Javascript事件循环)可能会导致Javascript代码执行的持续时间过长。这在浏览器中很糟糕(因为阻塞)。

这个问题

在Javascript中,Q允许处理异步编程任务。大!

已经有一些实现和库围绕WinJSwhen.jsthen(onFullfilled,onReject)仅举几例。看了之后我就看到他们在Javascript异步编程挑战中处理了一些“特殊的东西”。

通常我认为他们这样做是为了解决承诺

  1. 转到承诺的内部列表
  2. 检查是否履行了承诺+运行所有相关的(通过qazxsw poi)功能。
  3. (在某些情况下,我们在这里完成)
  4. (在其他情况下,仍有“未决”承诺)

这种情况(4)是因为让它们(其余的承诺)满了将需要当前的Javascript代码(这是承诺解析的代码)停止运行并允许JS event loop发生(即异步事件,如XHR请求,或用户界面互动)。为了使这个(4)工作,承诺解决方案规范召回(即通过setTimeout / setImmediate)并在event loop运行之后继续,因此可能已经解决了一些“未决”承诺(=拒绝/已满)。

我担心的是,第1步和第2步可能会运行很长一段时间,只是在执行到event loop时才会执行,以防它似乎表示要解决一些“未决”的承诺。虽然在某些情况下(即在服务器/ Node.js上)“好”,但在浏览器中这是非常有问题的,因为即使向event loop释放执行并且UI没有阻塞也没有问题,但这并没有完成在我所见过的承诺的实施中。

因此我的问题是:你知道一个关心方面的promise实现(Javascript Promises库): 在浏览器中制作“long-running-code-non-blocking-UI”?

这意味着承诺解决方案将自愿释放执行回event loop,以便CSS动画,用户输入,鼠标交互,确实得到足够的关注,并且不会有“警告:无响应脚本”消息。

答案

任何兼容的promises实现都不会同步运行then函数,而只是在下一个tick。因此,您担心“第1步和第2步可能会运行很长一段时间”是没有根据的。

来自Promises / A +规范:

在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilledonRejected

这里的“平台代码”意味着引擎,环境和承诺实现代码。在实践中,这个要求确保onFulfilledonRejected异步执行,然后调用事件循环,并使用新堆栈。

换句话说,您在2)下的配方是不正确的。 promises实现不“运行相关的函数”,它会安排它们。

如果处理程序本身是“长时间运行”的代码,这对你无能为力 - 实际上没有办法帮助你。

另一答案

我认为解决方案可能是解析长时间运行的JavaScript代码,例如使用https://github.com/NeilFraser/JS-Interpreter

它会使代码更慢,但您可以指定优先级:

const myInterpreter = new Interpreter(myCode);
function nextStep() {
    if (myInterpreter.step()) {
        window.setTimeout(nextStep, 100/speed);
    }
}
nextStep();

以上是关于Javascript Promises库在浏览器中制作“长时间运行代码 - 非阻塞UI”?的主要内容,如果未能解决你的问题,请参考以下文章

现代JS中的流程控制:详解Callbacks Promises Async/Await

现代JS中的流程控制:详解Callbacks Promises Async/Await

Mongoose 的默认 Promise 库在 MEAN 堆栈中已弃用

JavaScript 中的 Promises/Fetch:如何从文本文件中提取文本

javascript 在系列#js #promise中运行Promises

javascript 在系列#js #promise中运行Promises