在this answer , 一个 promise 链是递归构建的。
稍微简化一下,我们有:
function foo() {
function doo() {
// always return a promise
if (/* more to do */) {
return doSomethingAsync().then(doo);
} else {
return Promise.resolve();
}
}
return doo(); // returns a promise
}
大概这会产生一个调用堆栈和一个 promise 链——即“深”和“宽”。
与单独执行递归或构建 promise 链相比,我预计内存峰值会更大。
最佳答案
a call stack and a promise chain - ie "deep" and "wide".
实际上,没有。这里没有 promise 链,正如我们从 doSomeThingAsynchronous.then(doSomethingAsynchronous).then(doSomethingAsynchronous).... 中了解到的那样(这就是 Promise.each 或 Promise .reduce 如果以这种方式编写,可能会顺序执行处理程序)。
我们在这里面对的是一个解析链1 - 当满足递归的基本情况时,最终会发生什么,类似于 Promise.resolve(Promise.resolve(Promise.resolve(…)))。如果你想这么调用它,这只是“深”,而不是“宽”。
I would anticipate a memory spike larger than either performing a recursion or building a promise chain alone.
实际上不是尖峰。随着时间的推移,您会慢慢地构建大量 promise ,这些 promise 由最内层的 promise 解决,所有 promise 都代表相同的结果。当您的任务结束时,条件得到满足并且最内层的 promise 以实际值解决,所有这些 promise 都应该以相同的值解决。这将以 O(n) 的成本结束,以沿着解析链前进(如果天真地实现,这甚至可能以递归方式完成并导致堆栈溢出)。之后,除了最外层的所有 promise 都可以被垃圾收集。
相比之下,由类似的东西构建的 promise 链
[…].reduce(function(prev, val) {
// successive execution of fn for all vals in array
return prev.then(() => fn(val));
}, Promise.resolve())
会显示一个尖峰,同时分配 n 个 promise 对象,然后慢慢地一个一个地解析它们,垃圾收集之前的对象,直到只有已解决的最终 promise 还活着。
memory
^ resolve promise "then" (tail)
| chain chain recursion
| /| |\
| / | | \
| / | | \
| ___/ |___ ___| \___ ___________
|
+----------------------------------------------> time
Is this so?
不一定。如上所述,该批量中的所有 promise 最终都使用相同的值2 解析,因此我们只需要一次存储最外层和最内层的 promise。所有中间 promise 可能会尽快被垃圾收集,我们希望在恒定的空间和时间中运行此递归。
事实上,这个递归结构对于 asynchronous loops 是完全必要的在动态条件下(没有固定数量的步骤),您无法真正避免它。在 Haskell 中,IO monad 一直使用 this,正是因为这种情况才对其进行了优化。它与 tail call recursion 非常相似,它通常会被编译器删除。
Has anyone considered the memory issues of building a chain in this way?
是的。这是 discussed at promises/aplus例如,虽然还没有结果。
许多 promise 库确实支持迭代助手来避免 promise then 链的尖峰,例如 Bluebird 的 each 和 map 方法。
我自己的 promise 库3,4 确实具有解析链的功能,而不会引入内存或运行时开销。当一个 promise 采用另一个(即使仍然悬而未决)时,它们变得无法区分,并且中间的 promise 不再在任何地方被引用。
Would memory consumption differ between promise libs?
是的。虽然这种情况可以优化,但很少能做到。具体来说,ES6 规范确实要求 Promises 在每次 resolve 调用时检查值,因此折叠链是不可能的。链中的 promise 甚至可以用不同的值解决(通过构建一个滥用 setter/getter 的示例对象,而不是在现实生活中)。问题was raised on esdiscuss但仍未解决。
因此,如果您使用泄漏实现,但需要异步递归,那么您最好切换回回调并使用 deferred antipattern将最内层的 promise 结果传播到单个结果 promise 。
[1]:没有官方术语
[2]:好吧,他们互相解决了。但是我们希望用相同的值解析它们,我们期望
[3]:无证 Playground ,通过 aplus。阅读代码后果自负:https://github.com/bergus/F-Promise
[4]:也在 this pull request 中为 Creed 实现
关于javascript - 在 javascript 中递归构建 promise 链 - 内存注意事项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29925948/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo
作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
我经常迷上ruby的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情