首页 > 解决方案 > Nodejs 中的无限循环

问题描述

在使用 nodejs 制作链接 Shortner 脚本时,我遇到了以下问题:我的程序进入了无限循环,原因是我忽略了这里的代码:

function makeShort() {
    var short = "";
    var cond = true;

    while(cond){
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

        for(var i = 0; i < length; i++){
            short += possible.charAt(Math.floor(Math.random() * possible.length));
        }

        let query = {short:short};

        Link.findOne(query, (err, link)=>{
            if(err) throw err;
            if(!link){
                console.log("here");
                cond = false;

            }
        });
    }
    return short;
}

然后在这里使用它:

router.post('/', (req, res)=>{
    let short = makeShort();
    const newLink = new Link({
        url: req.body.url,
        short:short
    });

    newLink.save().then(link => {
        res.json(link);
    });
});

这个想法是我生成一个随机字符串(5个字符),然后,如果它存在,我创建另一个,依此类推..直到我找到一个未使用的字符串(数据库是空的,所以没有理由它进入无限循环)。

标签: javascriptnode.jsloopsinfinite

解决方案


您可以使用循环遍历并测试数据库中的值async/await。我们所做的是将您的函数转换为异步函数,然后创建一个新函数,该函数将返回一个将解析的承诺true/false

接下来,我们在 while 循环中调用该函数,并await为将包含的结果true/false设置为变量cond并继续循环。

它看起来像这样:

async function makeShort(length) {
  let cond = true;

  while (cond) {
    let short = (Math.random() * 1000).toString(32).replace(/\./g, '').substr(0, length);

    let query = { short: short };
    cond = await findOne(query);
  }
  return short;
}

function findOne(query) {
  return new Promise(resolve => {
    Link.findOne(query, (err, link) => {
      if (err) resolve(false);
      if (!link) {
        return resolve(false);
      }
      return resolve(true);
    });
  })
}

然后我们可以这样调用它let short = await makeShort()(我们还必须使用 make(req, res)函数async):

router.post('/', async (req, res) => {
  let short = await makeShort();
  const newLink = new Link({
    url: req.body.url,
    short: short
  });

  newLink.save().then(link => {
    res.json(link);
  });
});

推荐阅读