Javascript 如何在循环中按顺序运行请求?
这是我试图实现的一个伪代码。首先,我需要从请求主体获取url列表,然后将这些url传递给请求函数(使用请求模块),请求函数将从每个url获取数据,然后将这些数据保存到MongoDB。完成所有请求(包括仅将数据保存到服务器)后,服务器应发送响应Javascript 如何在循环中按顺序运行请求?,javascript,node.js,mongodb,express,request,Javascript,Node.js,Mongodb,Express,Request,这是我试图实现的一个伪代码。首先,我需要从请求主体获取url列表,然后将这些url传递给请求函数(使用请求模块),请求函数将从每个url获取数据,然后将这些数据保存到MongoDB。完成所有请求(包括仅将数据保存到服务器)后,服务器应发送响应 app.post('/', (req, resp) => { const { urls } = req.body; urls.forEach((url, i) => { request(url, funct
app.post('/', (req, resp) => {
const { urls } = req.body;
urls.forEach((url, i) => {
request(url, function (err, resp, body) {
if (err) {
console.log('Error: ', err)
} else {
// function to save data to MongoDB server
saveUrlData(body);
console.log(`Data saved for URL number - ${i+1}`)
}
})
});
// Should be called after all data saved from for loop
resp.send('All data saved')
})
我已经尝试过这段代码,当然resp.send()函数将在不考虑请求是否已完成的情况下运行。使用此代码,我在控制台上得到如下结果:
Data saved for URL number - 3
Data saved for URL number - 1
Data saved for URL number - 5
Data saved for URL number - 2
Data saved for URL number - 4
我可以用嵌套的形式编写它们,但是变量url
可以有任意数量的url,这就是为什么至少从我的理解来看,它需要在循环中。我希望请求按顺序运行,即它应该解析第一个url,然后解析第二个url,依此类推,当所有url都完成时,它应该响应。请帮忙 你应该看看
否则,您可以执行如下递归请求:
app.post('/', (req, resp) => {
const { urls } = req.body;
sendRequest(urls, 0);
})
function sendRequest(urlArr, i){
request(urlArr[i], function (err, resp, body) {
if (err) {
console.log('Error: ', err)
}
else {
saveUrlData(body);
console.log(`Data saved for URL number - ${i+1}`)
}
i++;
if(i == urlArr.length) resp.send('All data saved') //finish
else sendRequest(urlArr, i); //send another request
})
}
我所要做的就是创建一个单独的函数,可以反复调用,将url数组和基索引0作为参数传递。每次成功回调都会增加我在同一函数中再次传递的索引变量。冲洗并重复,直到我的索引达到url数组的长度,我将从此处停止递归循环
app.post('/', async (req, resp) => {
const {
urls
} = req.body;
for (const url of urls) {
try {
const result = await doRequest(url)
console.log(result)
} catch (error) {
// do error processing here
console.log('Error: ', err)
}
}
})
function doRequest(url) {
return new Promise((resolve, reject) => {
request(url, function(err, resp, body) {
err ? reject(err) ? resolve(body)
})
})
}
使用
您希望等待所有api响应并存储在db中,因此您应该执行异步等待并提示所有响应。 您可以使用请求承诺模块而不是请求。因此,您将在每个请求的api调用上获得承诺,而不是回调。 并使用promise.all在阵列内推高所有请求(模块)调用。 使用async wait,代码执行将等待所有api调用得到响应并存储在db中
const rp = require('request-promise');
app.post('/', async (req, res) => {
try{
const { urls } = req.body;
// completed all will have all the api resonse.
const completedAll = await sendRequest(urls);
// now we have all api response that needs to be saved
// completedAll is array
const saved = await saveAllData(completedAll);
// Should be called after all data saved from for loop
res.status(200).send('All data saved')
}
catch(err) {
res.status(500).send({msg: Internal_server_error})
}
})
function sendRequest(urlArr, i){
const apiCalls = [];
for(let i=0;i < urlArr.length; i++){
apiCalls.push(rp(urlArr[i]));
}
// promise.all will give all api response in order as we pushed api call
return Promise.all(apiCalls);
}
const rp=require('request-promise');
app.post('/',异步(req,res)=>{
试一试{
const{url}=req.body;
//全部完成后将具有所有api响应。
const completedAll=等待发送请求(URL);
//现在我们有了所有需要保存的api响应
//completedAll是数组
const saved=等待saveAllData(completedAll);
//应在从for循环保存所有数据后调用
res.status(200).send('所有数据已保存')
}
捕捉(错误){
res.status(500).send({msg:Internal_server_error})
}
})
函数sendRequest(urlArr,i){
常量apicall=[];
for(设i=0;i
您可以参考以下链接:
查看意图(一个爬虫),您可以使用承诺。所有这些都是因为URL不相互依赖
app.post('/', (req, resp) => {
const { urls } = req.body;
const promises = urls.map((url, i) => {
return new Promise((resolve, rej)=>{
request(url, function (err, resp, body) {
if (err) {
rej(err);
} else {
resolve(body);
}
})
})
.then((body)=>{
//this should definitely be a promise as you are saving data to mongo
return saveUrlData(body);
})
});
// Should be called after all data saved from for loop
Promise.all(promises).then(()=>resp.send('All data saved'));
})
注意:还需要进行错误处理。有多种方法可以解决此问题
- 您可以使用
async/await
- 许诺
- 您也可以使用
请求
不是基于承诺的模块,您不能直接等待它。您需要首先提示它,或者可以使用axios
我希望请求按顺序运行,即它应该解析第一个url,然后解析第二个url,依此类推,当所有url都完成时,它应该响应
,但没有url依赖于其他url。所以也许你应该让它们平行。这会快得多。正是我要找的。但是如何使用async和Wait捕捉错误呢?例如,在sendRequest
中,如果rp()
在解析url时抛出错误,我将如何捕获该错误?如果有一个URL没有解析,它会停止解析其他URL吗?为了捕获错误,我使用了catch块。当我们使用async和Wait时,必须在try-catch块中使用它。如果sendRequest或saveAllData方法中的任何一个抛出错误或拒绝承诺,那么它将在catch块中处理。如果任何一个url没有解析,那么它将停止解析其他url,并直接拒绝该承诺。理想情况下,不应该出现错误,我们应该在api调用之前进行适当的数据验证,以便始终得到响应200。
app.post('/', (req, res, next) => {
const { urls } = req.body;
async.each(urls, get_n_save, err => {
if (err) return next(err);
res.send('All data saved');
});
function get_n_save (url, callback) {
request(url, (err, resp, body) => {
if (err) {
return callback(err);
}
saveUrlData(body);
callback();
});
}
});