Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么Q.js承诺在解决后是异步的?_Javascript_Angularjs_Promise - Fatal编程技术网

Javascript 为什么Q.js承诺在解决后是异步的?

Javascript 为什么Q.js承诺在解决后是异步的?,javascript,angularjs,promise,Javascript,Angularjs,Promise,如果我有以下资料: var deferred = Q.defer(); deferred.resolve(); var a = deferred.promise.then(function() { console.log(1); }); console.log(2); …为什么我在控制台中看到2,然后是1 根据Promissions规范,我理解此输出是正确的,该规范规定在下一次勾选时调用函数(例如,setTimeout()),即使它已经解决,但我不理解为什么 我想让代码

如果我有以下资料:

var deferred = Q.defer();

deferred.resolve();

var a = deferred.promise.then(function() {
    console.log(1);    
});

console.log(2); 
…为什么我在控制台中看到2,然后是1

根据Promissions规范,我理解此输出是正确的,该规范规定在下一次勾选时调用函数(例如,
setTimeout()
),即使它已经解决,但我不理解为什么

我想让代码同步调用一系列承诺,假设所有承诺都已解决

我真正的用例是,我试图使用Angular的实现,
$q
,我希望所有的
回调都在相同的
$digest
周期中执行,这样我就不会得到不必要的后续
$digest
周期。

答案是一致性

在实际代码中,您没有承诺在创建时总是立即得到解决,它们将是毫无意义的。所以你有承诺,有时可能会立即解决

在这种情况下,您不希望有不同的流。您希望始终保持相同的、可预测的流程。因此,您希望下一个函数总是在下一个滴答声时被调用


当你不需要承诺时,不要使用承诺。

这是基于一系列观点和假设的设计错误。它之所以被锁定,是因为它是在委员会设计过程中未经全面技术验证而匆忙推出的,这一过程也受到了许多供应商实施自己设计的背压,同样的错误使得它很难回溯

一旦JS标准发布到web上,它就可以被撤销,即使它被打破了,因为网页不应该被打破。如果今天有人写了一个页面,然后就死了,那么五年后在你的浏览器中仍然可以看到它。如果你在浏览网页时不断地碰到与你的浏览器不兼容的页面,那将是一个很大的问题

在非常简单的用例中,它不会造成太大的伤害,并且消除了关于某些东西是否可能是异步的混淆

对于越来越不平凡的用例,它会造成越来越多的伤害并增加混乱。起初,它似乎使您更容易对代码进行推理,但它牺牲了不那么琐碎的使用,而获得了最少琐碎的使用

总的来说,如果代码在下一个周期中没有运行完全不需要异步的东西,那么对代码进行推理就容易多了。这是一种选择破坏二级语言以迎合一级用户的情况,代价是二级及以上用户,而不是帮助一级用户提升到二级用户。这是一个居高临下或悲观的设计决策

有一种中间解决方案,可以像在当前代码运行到完成之后运行一样运行每个任务,但事情是按正确的顺序安排的。这一点还没有得到实施,这也是有争议的,因为妥协并不总是产生最好的解决方案。这种折衷为直接返回调用堆栈带来了性能问题

promises的工作方式意味着前向调用堆栈是深度优先的,运行到完成(隔离),而返回调用堆栈是广度优先的,并与其他返回调用堆栈交错运行。这是两种截然不同的概念和行为。传统上,回调都以相同的方式运行

这也意味着你不能天真地用承诺或任何基于承诺的东西来取代回调。回拨给你更多的选择,承诺带走。如果用承诺替换回调而不考虑这一差异,则可以创建具有稳定性问题和潜在安全问题的代码,因为无序事件的这种行为可能会导致当前代码流意外跳转

你不能依赖订单,这意味着在有些情况下,如果你要求很多东西,当你把它们拿回来时,你必须再次检查它们是你要求的东西,因为你不需要用回调来做这件事。您可能还需要缓冲和重新排序不需要回调的事件。如果您不小心将正在运行的两件事情隔离开来,那么基准测试也会变得不可靠

这也会造成严重的性能瓶颈,而这些瓶颈往往是您无法轻松避免的。如果您使用Promission,一次从单个事件返回一百个返回结果到迭代器,每个返回调用花费一秒钟,它们的promise resolve depth是两个,那么它们将被分成两半,前两半都运行,后两半都运行。这意味着任何事情都需要50.5秒才能完成,就像50秒后的回调一样,其中一半已经完成。如果任务的结果被传递给另一个外部服务进行处理,那么当该服务可能正在处理您的结果时,它会让该服务闲置50秒。当您希望在承担负载的服务下同时获得低延迟和高吞吐量时,这使得承诺变得非常糟糕,这表明了设计的弱点

不能天真地用承诺替换回调是这个设计错误最具破坏性的后果之一,这个错误也会遗留到async/await中。如果要转换回调库,不能简单地更改语法,必须仔细检查每一点的语义


没有计划解决这个问题。您可以创建自己的承诺,并且可以使用生成器提供与async/await相同的语法,但具有与回调相同的可预测和高性能行为。然而,与其他仍然依赖本机承诺的库打交道时,您可能会遇到问题。

我认为技术术语是“不要释放Zalgo”,一个方法必须始终是异步或同步的,否则您会遇到非常奇怪的竞争条件,这会让您哭泣。@BenjaminGruenbaum感谢您的回答。也许我不想要承诺。我想要一个整洁的请求方式