【问题标题】:Recursive auto increment function in not resolving递归自动增量功能无法解析
【发布时间】:2020-07-15 11:13:28
【问题描述】:

长话短说,我正在使用此函数来获取用户的唯一用户名,但它可能已经存在 - 在这种情况下,它应该再次运行,直到没有用户使用它。问题是当从内部再次调用时,该函数无法解析。该函数本身正在运行(它正在更新 mongodb 中的文档),但我无法获得序列号。我究竟做错了什么? 任何建议表示赞赏。

const getNextUsername = () => {
  return new Promise((res, rej) => {
    Counter.findByIdAndUpdate('usernames', {
      $inc: {
        sequence: 1
      }
    }, {
      upsert: true,
      new: true
    }, (err, result) => {
      if (err) rej(err);

      User.findOne({
        username: result.sequence
      }, (err, u) => {
        if (err) rej(err);

        if (u) {
          // if user with same username exists call the function again
          // and here something fails
          getNextUsername();
        } else {
          res(result.sequence);
        }
      })
    })
  })
}

如果这很重要,我会从另一个函数调用它并将其分配给带有 async/await 的 const。

  const autoIncremented = await getNextUsername();
  console.log(autoIncremented); // this actually never logs

【问题讨论】:

    标签: javascript mongoose


    【解决方案1】:

    问题是当你递归调用getNextUsername() 时,你并没有解决最外层的 Promise。该调用将产生一个新的 Promise 并且(也许)将被解决,但该值将无处可去,因为它没有被使用。

    由于getNextUsername() 确实产生了一个 Promise 并且它(希望)用一个值解析,你可以通过添加解析步骤来非常简单地修改你的代码: p>

    const getNextUsername = () => {
      return new Promise((res, rej) => {
        Counter.findByIdAndUpdate('usernames', {
          $inc: {
            sequence: 1
          }
        }, {
          upsert: true,
          new: true
        }, (err, result) => {
          if (err) rej(err);
    
          User.findOne({
            username: result.sequence
          }, (err, u) => {
            if (err) rej(err);
    
            if (u) {
              //after the recursive call completes, resolve with the returned value or fail if it failed
              getNextUsername()
                .then(res)
                .catch(rej); 
            } else {
              res(result.sequence);
            }
          })
        })
      })
    }
    

    这样,当后续的 Promise 被解析时,您可以将解析后的值传播到 Promise 之外。不管你有多少承诺,即使你有 Promise1 -> Promise2 -> Promise3 当第三个解决时,第二个将调用.then(res) 并返回值,这将再次调用.then(res)第一个 Promise 并将值推出。

    .catch(rej) 会做类似的事情,但会有错误 - 如果任何内部承诺失败,所有到顶部的承诺都会失败。

    这是一个非常简单的递归函数实现,它使用 Promises 来说明这个想法:

    function recursiveSum(a, b, debugPrefix = ">") {
      return new Promise((res, rej) => {
        console.log(debugPrefix, "recursively summing", a, b);
        if (b <= 0) {
          console.log(debugPrefix, "result found");
          res(a);
        } else {
          console.log(debugPrefix, "going deeper");
          recursiveSum(a+1, b-1, debugPrefix + ">")
            .then(res);
        }
      })  
    }
    
    
    recursiveSum(5, 3)
      .then(console.log);

    最后说明:我不知道这是否是解决您的问题的最佳方法。我不熟悉 MongoDB,也许有更好的方法。我的解决方案是简单地修复当前代码。

    【讨论】:

    • 非常感谢,伙计!我完全错过了。 * 是的,这可能不是最好的方法,但现在还可以。再次感谢您的帮助!
    猜你喜欢
    • 2013-12-01
    • 2021-11-13
    • 2011-08-14
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多