我写了一段代码,它有两个参数,第一个是一些 URL,第二个是一个整数,表示必须下载 URL 的次数(我知道一次又一次下载相同的 URL 没有意义,但是这段代码只是一个示例,在实际代码中,URL 是从数据库表中随机选择的),到目前为止,代码是作为递归函数编写的。这是我当前代码的样子,
const request = require("request");
function downloadUrl(url, numTimes) {
if (numTimes > 0) {
console.log(url, numTimes);
request.get(url, function (err, resp, buffer) {
if (err) {
return err;
}
console.log(`MimeType: ${resp.headers['content-type']}, Size: ${buffer.length}, numTimes: ${numTimes}`);
downloadUrl(url, --numTimes);
});
}
}
function main() {
downloadUrl('http://somerandomurl', 5); // the URL here might get picked randomly from an array or a table
}
main();
我想知道的是,这个递归代码可以写成使用 while 或 for 循环的迭代代码吗?我尝试编写以下代码,
function downloadUrl(url, numTimes) {
for (let i = 0; i< numTimes; i++) {
request.get(url, function (err, resp, buffer) {
if (err) {
return err;
}
console.log(`MimeType: ${resp.headers['content-type']}, Size: ${buffer.length}, numTimes: ${numTimes}`);
});
}
}
但这段代码似乎是并行执行的,这显然是因为在 Node.js 中,异步代码不会等待语句完成才继续执行下一条语句,这与 Java 等编程语言不同。
我的问题是,有没有一种方法可以让我编写的迭代代码的行为与我的递归代码完全一样?我的递归代码顺序执行,其中 numTimes 变量递减 1 并从 5 到 1 顺序打印。
我已尽力让我的问题清晰明了,但如果有什么不清楚或令人困惑的地方,请随时提问。
最佳答案
我猜你想结束你的 http 请求以发出另一个请求,如果我错了请纠正我,但你可以在你的方法中使用 await。
const request = require('request');
async function downloadUrl(url, numTimes) {
for (let i = 0; i< numTimes; i++) {
const objToResolve = await doDownload(url);
if(objToResolve.err){
console.log(`Error: ${objToResolve.err}, try: ${i}`);
}else{
console.log(`Size: ${objToResolve.buffer.length}, try: ${i}`);
}
}
}
// wrap a request in an promise
function doDownload(url) {
return new Promise((resolve, reject) => {
request(url, (err, resp, buffer) => {
if (err) {
reject({err});
}else{
resolve({err, resp, buffer});
}
});
});
}
// now to program the "usual" way
// all you need to do is use async functions and await
// for functions returning promises
function main() {
console.log('main chamado');
downloadUrl('http://www.macoratti.net/11/05/c_aspn3c.htm', 5);
}
main();
编辑: 通过考虑超时,您可以更好地处理您的请求
const request = require('request');
async function downloadUrl(url, numTimes) {
for (let i = 0; i< numTimes; i++) {
try{
const objToResolve = await doDownload(url);
if(objToResolve.err){
console.log(`Error: ${objToResolve}, try: ${i}`);
}else{
console.log(`Size: ${objToResolve.buffer.length}, try: ${i}`);
}
}catch(timeout){
console.log(`Error: ${timeout}, try: ${i}`);
}
}
}
// wrap a request in an promise
function doDownload(url) {
const timeout = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('timeout'));
}, 300);
});
const requestPromisse = new Promise((resolve, reject) => {
request({uri:url, timeout:3000}, (err, resp, buffer) => {
if (err) {
reject({err});
}else{
resolve({err, resp, buffer});
}
});
});
return Promise.race([timeout,requestPromisse]);
}
// now to program the "usual" way
// all you need to do is use async functions and await
// for functions returning promises
function main() {
console.log('main called');
downloadUrl('http://www.macoratti.net/11/05/c_aspn3c.htm', 5);
}
// run your async function
main();
关于javascript - 可以在 NodeJS/Javascript 中使用 while/for 循环将此递归代码编写为迭代代码吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57663273/