sil*_*orb 8 javascript c++ performance promise
考虑以下JavaScript代码:
var promise = new Promise();
setTimeout(function() {
promise.resolve();
}, 10);
function foo() { }
promise.then(foo);
Run Code Online (Sandbox Code Playgroud)
在我看过的promise实现中,promise.resolve()只是设置了一些属性来表明promise被解析了,foo()稍后会在事件循环中被调用,但似乎promise.resolve()会有足够的信息可以立即调用任何延迟函数,如foo().
事件循环方法似乎会增加复杂性并降低性能,为什么要使用它?
虽然我对promise的大多数使用都是使用JavaScript,但我的问题的一部分原因是在C++游戏等性能密集的情况下实现承诺,在这种情况下,我想知道是否可以利用promises的一些好处而不使用事件循环的开销.
所有承诺实施,至少是好的实现.
这是因为将同步性混合到异步API中正在释放Zalgo.
事实承诺有时不会立即解决,延迟有时意味着API是一致的.否则,您将按执行顺序获得未定义的行为.
function getFromCache(){
return Promise.resolve(cachedValue || getFromWebAndCache());
}
getFromCache().then(function(x){
alert("World");
});
alert("Hello");
Run Code Online (Sandbox Code Playgroud)
事实承诺库推迟,意味着保证上述块的执行顺序.在像jQuery这样的破坏承诺实现中,顺序会根据是否从缓存中获取项目而更改.这很危险.
具有非确定性执行顺序是非常危险的,并且是错误的常见来源.Promises/A +规范让你在这里成功.
是否promise.resolve()同步或异步执行其延续实际上取决于实现.
此外,"事件循环"不是提供不同"执行上下文"的唯一机制.可能还有其他方法,例如线程或线程池,或者考虑提供调度队列的GCD(Grand Central Dispatch,dispatch lib).
Promises/A + Spec明确要求相对于调用方法的"执行上下文" 异步执行continuation(onFulfilled相应的onRejected处理程序).then
onFulfilled或者onRejected在执行上下文堆栈仅包含平台代码之前不得调用.[3.1].
根据Notes,您可以阅读实际含义:
这里的"平台代码"意味着引擎,环境和承诺实现代码.实际上,这个要求确保onFulfilled和onRejected异步执行,然后调用事件循环,然后调用新堆栈.
在这里,每个事件将在不同的"执行上下文"上执行,即使这是相同的事件循环,也是相同的"线程".
由于Promises/A +规范是为Javascript环境编写的,因此更通用的规范只需要相对于调用该方法的调用者异步执行continuation then.
这样就有很好的理由!
示例(伪代码):
promise = async_task();
printf("a");
promise.then((int result){
printf("b");
});
printf("c");
Run Code Online (Sandbox Code Playgroud)
假设,处理程序(continuation)将在与调用站点相同的线程上执行,执行顺序应该是控制台显示:
acb
Run Code Online (Sandbox Code Playgroud)
特别是,当一个promise已经解决时,一些实现倾向于在同一个执行上下文中"立即"(即同步)调用continuation .这显然违反了上述规则.
规则始终异步调用延续的原因是,调用站点需要保证then在任何方案中包含continuation语句之后的处理程序和代码的执行的相对顺序.也就是说,无论承诺是否已经解决,声明的执行顺序必须相同.否则,更复杂的异步系统可能无法可靠运行.
对于具有多个同时执行上下文的其他语言中的实现的另一个糟糕的设计选择 - 比如多线程环境(在JavaScript中无关,因为只有一个执行线程),是关于函数同步调用continuation resolve.当异步任务将在稍后的事件循环周期中完成时,这甚至是有问题的,因此连续将确实相对于呼叫站点异步执行.
但是,当resolve异步任务完成时将调用该函数时,此任务可以在私有执行上下文(例如"工作线程")上执行.这个"工作线程"通常是一个专用的,可能是特殊配置的执行上下文 - 然后调用resolve.如果该resolve函数将同步执行延续,则继续将在任务的私有执行上下文上运行 - 这通常是不希望的.