Javascript 如果链接太多的话,会对性能产生什么影响?那么承诺呢?

Javascript 如果链接太多的话,会对性能产生什么影响?那么承诺呢?,javascript,promise,reduce,Javascript,Promise,Reduce,我有一个reduce的实现,它可能将许多处理程序链接在一起 const reduceIterable = (fn, x0, x) => { const iter = x[Symbol.iterator].call(x) let cursor = iter.next() if (cursor.done) { throw new TypeError('reduce(...)(x); x cannot be empty') } let y = !isUndefined

我有一个reduce的实现,它可能将许多
处理程序链接在一起

const reduceIterable = (fn, x0, x) => {
  const iter = x[Symbol.iterator].call(x)
  let cursor = iter.next()
  if (cursor.done) {
    throw new TypeError('reduce(...)(x); x cannot be empty')
  }
  let y = !isUndefined(x0) ? fn(x0, cursor.value) : (() => {
    const x0 = cursor.value
    cursor = iter.next()
    return cursor.done ? x0 : fn(x0, cursor.value)
  })()
  cursor = iter.next()
  while (!cursor.done) {
    const { value } = cursor
    y = isPromise(y) ? y.then(res => fn(res, value)) : fn(y, value)
    cursor = iter.next()
  }
  return y
}

// you would use reduce like reduce(add, 0)([1, 2, 3]) // => 6
const reduce = (fn, x0) => {
  if (!isFunction(fn)) {
    throw new TypeError('reduce(x, y); x is not a function')
  }
  return x => {
    if (isIterable(x)) return reduceIterable(fn, x0, x)
    if (isAsyncIterable(x)) return reduceAsyncIterable(fn, x0, x)
    if (is(Object)(x)) return reduceObject(fn, x0, x)
    throw new TypeError('reduce(...)(x); x invalid')
  }
}
具体来说,我看的是
y.then(res=>fn(res,value))
。因为这个,我晚上睡不着。我知道从那时起,承诺已经走了很长一段路,但这一点从未得到解决。我真的想知道我是否可以像这样使用Promise API,或者我是否需要做一些更难的事情

链接过多的
会对性能产生什么影响(如果有的话)

如果比较一个
.reduce()
循环,其中链接了大量
.then()
以对异步操作排序,并将其与异步函数中的
wait
循环进行比较,在异步函数中,在开始下一个操作之前完成一个操作,主要区别在于内存使用峰值。将大量
。然后()
链接在一起,将同时拥有内存中所有promise对象的完整链。如果执行
wait
循环,则一次只有一个承诺处于活动状态

现在,承诺不是大对象,所以即使你的链有数千个元素长,也可能不会有实质性的区别。但是,如果希望最小化峰值内存使用,则
await
循环将保持较低的峰值内存使用率

至于纯粹的执行速度,故事和往常一样。如果您真的关心执行速度,那么您必须使用
.reduce()
循环编写一个具有代表性的测试程序,并使用
wait
循环生成等效的输出和排序,并对两者进行基准测试。性能是如此依赖于特定的环境,如果你真的想知道哪个更快,你就必须衡量。理论往往是错误的,因为我们的直觉并不总是知道真正的瓶颈是什么。你必须测量


仅供参考,
async/await
在最近几个nodejs版本中的速度提高了不少。

一次创建尽可能多的可重用元素,这可能不利于通用函数。它完全分解为无限多个

在检测到承诺时,可以使用异步函数:

const reduceAwait=async(fn,initial,iterable)=>{
让m=等待初始值
for(可测常数){
m=等待fn(m,n)
}
返回m
}
常量可还原=(fn,初始,可还原)=>{
常量迭代器=iterable[Symbol.iterator]()
设m=初始值
如果(初始===未定义){
const first=iter.next()
如果(首先,完成){
抛出新的TypeError('减少没有初始值的空iterable')
}
m=第一个值
}
for(迭代器的常数n){
m=fn(m,n)
如果(i建议(m)){
返回reduceAwait(fn,m,迭代器)
}
}
返回m
}
m=wait fn(m,n)
也可以成为

m=fn(m,n)
如果(i建议(m)){
m=等待m
}

如果您希望混合输入的微任务最少。

老实说,微优化是不值得的。它可能会泄漏一些内存,但从长远来看不会对性能造成太大影响。如果您真的想要最大的性能,您可以使用像Bluebird这样的Promise库。请参阅这篇文章,了解与不支持异步函数的JavaScript环境的向后兼容性?异步函数很好地解决了创建过多承诺的问题。@Ry-异步函数最终不是承诺的语法糖吗?i、 e.相同数量的承诺和相同的性能?@Ry-这是针对
reduce
的一个功能,您可以在其中放置一个完全同步的功能,并使评估同步,但也可以在其中放入一个异步函数,并让它返回一个promiseFWIW。我不认为编写这样的重载函数是一个好主意。我必须说我同意你的观点。我将从中编写一些性能测试。刚刚创建了一个我喜欢的想法,打破了异步;它当然解决了一次性创建一堆承诺的问题!我很可能会按照这些思路实施一些东西。