以下模式调用返回承诺的递归 JavaScript 函数有什么区别? [英] What is the difference in following pattern to call recursive JavaScript function which returns a promise?

查看:22
本文介绍了以下模式调用返回承诺的递归 JavaScript 函数有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在具有 100000 条记录的以下代码中,recursiveFnReturnsPromiseV1 执行良好,而 recursiveFnReturnsPromiseV2 因堆栈外异常而失败.两者之间的唯一区别是 promise 的递归方式.在 v1 中,递归位于第一个 promise 的then"内,而在 v2 中,递归位于原始 promise 本身内.有什么区别?

In following code with 100000 records recursiveFnReturnsPromiseV1 executes fine while recursiveFnReturnsPromiseV2 fails with out of stack exception. The only difference between two is the way promises are being recursed. In the v1, the recursion is within a "then" of the first promise while in v2, the recursion is within the original promise itself. What's the difference?

let aValues = Array(100000);


recursiveFnReturnsPromiseV1(aValues, 0).then(function() {
  let p = document.createElement('div');
  p.innerText = 'recursiveFnReturnsPromiseV1 finished';
  document.getElementById('v1').appendChild(p);
}, function() {
  let p = document.createElement('div');
  p.innerText = 'recursiveFnReturnsPromiseV1 failed';
  document.getElementById('v1').appendChild(p);
})

recursiveFnReturnsPromiseV2(aValues, 0)
  .then(function() {
    let p = document.createElement('div');
    p.innerText = 'recursiveFnReturnsPromiseV2 finished';
    document.getElementById('v2').appendChild(p);
  }, function() {
    let p = document.createElement('div');
    p.innerText = 'recursiveFnReturnsPromiseV2 failed';
    document.getElementById('v2').appendChild(p);
  })

function recursiveFnReturnsPromiseV1(pValues, ix) {
  if (pValues.length <= ix)
    return Promise.resolve();

  return new Promise(function(c, e) {
    document.getElementById('v1').innerText = ix + 'v1' + Date.now();
    c();
  }).then(function() {
    return recursiveFnReturnsPromiseV1(pValues, ++ix);
  })



}

function recursiveFnReturnsPromiseV2(pValues, ix) {
  if (pValues.length <= ix)
    return Promise.resolve();


  return new Promise(function(c, e) {
    document.getElementById('v2').innerText = ix + 'v2' + Date.now();

    recursiveFnReturnsPromiseV2(pValues, ++ix).then(function() {
      c();
    }, function(err) {
      e()
    });
  })
}

<div id='v1'></div>
<div id='v2'></div>

推荐答案

让我们去掉 Promise 构造器反模式,并使用简单的 Promise.resolve 代替.你的函数现在变成

Lets strip away the Promise constructor antipattern, and use a simple Promise.resolve instead. Your functions now become

function recursiveFnReturnsPromiseV1(pValues, ix) {
  if (pValues.length <= ix)
    return Promise.resolve();

  let p = document.createElement('div');
  p.innerText = ix + 'v1' + Date.now();
  document.getElementById('v1').appendChild(p);

  return Promise.resolve().then(function() {
    return recursiveFnReturnsPromiseV1(pValues, ++ix);
  })
}

function recursiveFnReturnsPromiseV2(pValues, ix) {
  if (pValues.length <= ix)
    return Promise.resolve();

  let p = document.createElement('div');
  p.innerText = ix + 'v2' + Date.now();
  document.getElementById('v2').appendChild(p);

  return Promise.resolve(recursiveFnReturnsPromiseV2(pValues, ++ix));
}

现在应该很明显为什么第二个函数会溢出堆栈了.

It should be obvious by now why the second function overflows the stack.

为什么不是第一个?因为递归调用在一个异步 then 回调中,这意味着它稍后(在外部调用返回之后)以新的调用堆栈开始.

Why doesn't the first as well? Because the recursive call is inside an asynchronous then callback, which means it starts later (after the outer call returned) with a fresh call stack.

这篇关于以下模式调用返回承诺的递归 JavaScript 函数有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆