Nodejs 中的无限循环
Infinite loop in Nodejs
在使用 nodejs 制作 link 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 个字符),然后,如果它存在,我创建另一个,依此类推。直到我找到一个未使用的字符串(顺便说一句,数据库是空的,所以它没有理由进入无限循环)。
您可以使用 async/await
循环并测试数据库中的值。我们所做的是将您的函数转换为异步函数,然后创建一个新函数,该函数将 return 一个将解析 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);
});
});
不要混用同步循环和异步条件更新。在 DoSomething
调用 returns 结果之前,保证 运行 while
主体尽可能多地使用类似的东西:
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();
});
}
while
同步循环 运行,这意味着它们会阻止线程进一步执行,直到它们完成。因为 link 缩短器是异步的,它被 while
循环阻塞。
要异步处理此代码,您可以 return a 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
在使用 nodejs 制作 link 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 个字符),然后,如果它存在,我创建另一个,依此类推。直到我找到一个未使用的字符串(顺便说一句,数据库是空的,所以它没有理由进入无限循环)。
您可以使用 async/await
循环并测试数据库中的值。我们所做的是将您的函数转换为异步函数,然后创建一个新函数,该函数将 return 一个将解析 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);
});
});
不要混用同步循环和异步条件更新。在 DoSomething
调用 returns 结果之前,保证 运行 while
主体尽可能多地使用类似的东西:
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();
});
}
while
同步循环 运行,这意味着它们会阻止线程进一步执行,直到它们完成。因为 link 缩短器是异步的,它被 while
循环阻塞。
要异步处理此代码,您可以 return a 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