Nodejs中的无限循环

时间:2018-07-12 18:16:25

标签: javascript node.js loops infinite

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

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个字符),然后,如果存在,我创建另一个字符串,依此类推..直到找到一个未被使用的字符串(数据库为空btw,所以有它没有理由进入无限循环)。

3 个答案:

答案 0 :(得分:0)

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

接下来,我们在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);
  });
});

答案 1 :(得分:0)

请勿混用同步循环和异步条件更新。这样的事情可以保证在while调用返回结果之前,尽可能多地运行DoSomething正文:

while(cond) {
  // call something async. don't wait for a result.
  DoSomething.asynchronous( () => { cond = false; });
  // then immediately restart the iteration
}

所以不要那样做。让您的makeShort异步生成一个简短的字符串。

const symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const symbolCount = symbols.length;

function makeShort(howMany) {
  howMany = howMany || 5;
  let short = "";
  while(howMany--) {
    short += symbols[(Math.random() * symbolCount)|0];
  }
  return short;
}

然后,独立于此进行验证:

function assignShortForm(req, res) {
  let short = makeShort();

  verifyShortIsAvailable(
    short,
    success => {
      // this short form was available
      new Link({ url: req.body.url, short }).save().then(link => res.json(link));
    }, error => {
      // try again. RNG is not your friend, and this COULD run a very long time.
      assignShortForm(req, res);          
    }
  );
}

使用该功能的路由器,而不是对其进行内联:

router.post('/', assignShortForm);

在这种情况下,verifyShortIsAvailable应该异步完成其工作:

verify verifyShortIsAvailable(short, resolve, reject) {
  Link.findOne(query, (err, link) => {
    if (err) return reject(err);
    if (link) return reject("...");
    return resolve();
  });
}

答案 2 :(得分:0)

while循环是同步运行的,这意味着它们会阻止线程继续执行直到完成。由于链接缩短器是异步的,因此被while循环阻止。

要异步处理此代码,您可以返回Promise

function makeShort() {

    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    // note length was previously undefined in the comparison. use possible.length or another arbitrary value
    for(var i = 0; i < possible.length; i++){
        short += possible.charAt(Math.floor(Math.random() * possible.length));
    }

    let query = {short:short};
    return new Promise((resolve, reject) => {
        Link.findOne(query, (err, link) => {
            if(err) return reject(err);
            resolve(link)
        });
    })
}

然后您可以像这样使用它...

let short = makeShort().then(shortLink => {
    // do something with the link
}).catch(err => {
    // handle the error
});

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises