这是对以下问题的更新,应该有助于找到答案
接受torazaburo的答案,他还引用了部分杰出的Javascript承诺/ A +定义,我想在此更新问题。
Promise/A+规范在第2.2.4点建议:
在执行之前,不得调用onPulfilled或onRejected 上下文堆栈仅包含平台代码。 3.1。
并进一步解释
这里的“平台代码”意味着引擎,环境和承诺 实施代码。在实践中,这个要求确保了这一点 在事件发生后,onFulfilled和onRejected异步执行 循环转入然后调用,并使用新堆栈。这可以 使用“宏任务”机制(如setTimeout或)实现 setImmediate,或者使用“微任务”机制 MutationObserver或process.nextTick。自承诺实施以来 被认为是平台代码,它本身可能包含任务调度 队列或“trampoline”,其中调用处理程序。
我期待在这个问题上找到的问题是,Promise实现Javascript代码本身被认为是平台代码的关键点,并且允许不通过事件循环来解决后续的承诺调用相关的onFulfilled
onRejected
个函数。这在Node.js(服务器)中是很好的,因为它避免了回到事件循环(离开执行堆栈)的不必要的回归,但也导致浏览器中的挑战,因为执行堆栈不是在解决潜在的大量Promise之间退出(它们本身可以生成新的Promises)。不离开执行堆栈并屈服于事件循环会导致浏览器出现意外(阻塞脚本警告/问题)。
"蹦床" Promise实现的任务调度导致这种需要,但是不必避免不时地将执行交还给Javascript事件循环。这样的功能允许将Promise用于较重的任务。 Promises for" long-running-code"在这个问题中搜索/要求。
澄清:过度长度"不是onFulfilled
函数的个体长度,而是由于Promise解析过程(当以这样的" trampoline"方式完成)将几个函数/回调连接在一起。我已经意识到,如果一个人onFulfilled
函数太长,那么通过使用任何类型的Promise实现都不会有任何帮助。
这里的交易是x promises的后续解析(在一个执行堆栈中,因此没有回到Javascript事件循环)可能会导致Javascript代码执行的持续时间过长。这在浏览器中很糟糕(因为阻塞)。
在Javascript中,Promises
允许处理异步编程任务。太好了!
已经有一些实现和库围绕Q,WinJS或when.js来命名。 看了之后,我发现他们已经解决了一些特殊问题"在Javascript异步编程中挑战。
通常我认为他们为承诺解决方案
执行此操作then(onFullfilled,onReject)
)功能。 这种情况(4)是因为让它们(其余的承诺)满了将需要当前的Javascript代码(这是承诺解析的代码)停止运行并允许JS {{ 1}}发生(即XHR请求或User-UI交互等异步事件)。为了使这个(4)工作,承诺解决方案正常安排召回(即通过setTimeout / setImmediate)并在event loop
运行后继续,因此可能会有一些"等待& #34;承诺已经解决(=拒绝/已满)。
我担心的是,第1步和第2步可能会运行很长一段时间,只有在event loop
执行时才会执行,以防它似乎已经解决了某些"待定"承诺。虽然"好的"在某些情况下(即在服务器/ Node.js上),在浏览器中存在很大问题,因为即使将执行释放到event loop
并且UI没有阻塞也没有问题,但这并没有完成在我所见过的承诺的实施中。
因此,我的问题是:
你知道一个关心方面的promise实现(Javascript Promises库):
制作"长期运行代码 - 非阻塞UI"在浏览器中?
这意味着承诺解析会自动将执行释放回event loop
,以便CSS动画,用户输入,鼠标交互确实得到足够的关注,并且没有"警告:无响应的脚本"消息。
答案 0 :(得分:2)
任何兼容的promises实现都不会同步运行then
函数,而只会在下一个tick处运行。因此,您担心“第1步和第2步可能会运行很长一段时间”是没有根据的。
来自Promises / A +规范:
在执行上下文堆栈仅包含平台代码之前,不得调用
onFulfilled
或onRejected
。此处“平台代码”表示引擎,环境和承诺实现代码。在实践中,此要求确保
onFulfilled
和onRejected
异步执行,然后在调用事件循环之后执行,并使用新堆栈。
换句话说,2)中的配方不正确。 promises实现不会“运行相关的函数”,它计划它们。
如果处理程序本身是“长时间运行”的代码,这对你无能为力 - 实际上没有办法帮助你。
答案 1 :(得分:0)
我认为解决方案可能是解析长期运行的JavaScript代码,例如使用https://github.com/NeilFraser/JS-Interpreter。
它会使代码更慢,但您可以指定优先级:
const myInterpreter = new Interpreter(myCode);
function nextStep() {
if (myInterpreter.step()) {
window.setTimeout(nextStep, 100/speed);
}
}
nextStep();