Node.js - 递归地尝试通过 fetch 发出 get 请求时卡住 api
Node.js - Getting stuck recursively trying to make get requests via fetch api
我正在查询一个端点,需要多次点击它才能获取所有数据。我正在尝试递归地执行此操作,因为我不知道在任何给定时间我需要进行多少次点击才能获得完整的数据集。
由于节点是非阻塞的方式,我真的很困惑。我理解为什么需要它,因为它是单线程的。但是,我正在努力以一种能够给我所需输出的方式实现我的代码。
我在这里读的越多,我就越不明白。
我只需要我的函数反复命中一个端点,直到我提取完所有数据。然后我想将这些数据推送到一个数组中。然后我想处理数据。
-查询端点的函数
async function getTwitch(url = "", data = {}) {
const response = await fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json',
"Authorization": "Bearer superSecret",
"Client-ID": "0asdbn3245kas364"
// 'Content-Type': 'application/x-www-form-urlencoded',
}
});
return response.json(); // parses JSON response into native JavaScript objects
}
-回调和全局变量
let test_BreakCase = 10;
let streams = [];
async function getLiveStreams(cursor = ''){
//create query parameter for pagination and build into url
let query = (cursor !== '') ? `after=${cursor}&` : '';
let baseURL = `https://api.twitch.tv/helix/streams?${query}first=100&language=en`;
//make fetch req for page; when promise returns iterate it and push data into array
getTwitch(baseURL)
.then(data => {
let cursor = data.pagination.cursor;
for(let i = 0; i < data.data.length; i++){
streams.push(data.data[i].user_login);
}
//if cursor not empty recursively call getTwitch()
if(cursor !== '' && data.pagination !== null && test_BreakCase > 10){
getLiveStreams(cursor);
}
});
}
-尝试检查数组中的值
const s = await getLiveStreams().then(data => {
console.log(streams);
});
谢谢
我不是专家,但是当我开始尝试在函数调用完成之前将递归函数的输出存储在函数外部时,我通常会做错事。如果您将流数组传递给递归函数会怎么样?这也解决了我注意到的另一个可能的问题,即通常基本情况和递归情况都应该 return 某些东西,无论是最终结果还是另一个递归调用。我们一直 return 调用 getLiveStreams
直到最终数据数组被 return 编辑,这使调用堆栈向上冒泡到对递归函数的初始调用。
async function getLiveStreams(cursor = '', streams = []) {
//create query parameter for pagination and build into url
let query = cursor !== '' ? `after=${cursor}&` : ''
let baseURL = `https://api.twitch.tv/helix/streams?${query}first=100&language=en`
const data = await getTwitch(baseURL)
cursor = data.pagination.cursor
for (let i = 0; i < data.data.length; i++) {
streams.push(data.data[i].user_login)
}
// base case: cursor is empty
if (cursor === '' || data.pagination === null) {
return streams
}
// recursive case
return await getLiveStreams(cursor, streams)
}
编辑:递归情况下的 return 可能也应该是等待,因为函数 return 是一个承诺。
Edit2:我用 jsonplaceholder 稍微测试了你代码的这个 re-written 版本并且它有效:
const https = require('https')
const _URL = 'https://jsonplaceholder.typicode.com/posts/'
async function getTwitch(url) {
return new Promise((resolve, reject) => {
let data = ''
https.get(url, (res) => {
res.on('data', (chunk) => {
data += chunk
})
res.on('end', () => resolve(JSON.parse(data)))
})
})
}
async function getLiveStreams(i = 1, streams = []) {
let baseURL = _URL + i.toString()
const data = await getTwitch(baseURL)
streams.push(data)
// base case: we've made 50 requests
if (i === 50) {
return streams
}
// recursive case
return await getLiveStreams(i + 1, streams)
}
getLiveStreams().then(results => console.log(results))
我正在查询一个端点,需要多次点击它才能获取所有数据。我正在尝试递归地执行此操作,因为我不知道在任何给定时间我需要进行多少次点击才能获得完整的数据集。
由于节点是非阻塞的方式,我真的很困惑。我理解为什么需要它,因为它是单线程的。但是,我正在努力以一种能够给我所需输出的方式实现我的代码。
我在这里读的越多,我就越不明白。
我只需要我的函数反复命中一个端点,直到我提取完所有数据。然后我想将这些数据推送到一个数组中。然后我想处理数据。
-查询端点的函数
async function getTwitch(url = "", data = {}) {
const response = await fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json',
"Authorization": "Bearer superSecret",
"Client-ID": "0asdbn3245kas364"
// 'Content-Type': 'application/x-www-form-urlencoded',
}
});
return response.json(); // parses JSON response into native JavaScript objects
}
-回调和全局变量
let test_BreakCase = 10;
let streams = [];
async function getLiveStreams(cursor = ''){
//create query parameter for pagination and build into url
let query = (cursor !== '') ? `after=${cursor}&` : '';
let baseURL = `https://api.twitch.tv/helix/streams?${query}first=100&language=en`;
//make fetch req for page; when promise returns iterate it and push data into array
getTwitch(baseURL)
.then(data => {
let cursor = data.pagination.cursor;
for(let i = 0; i < data.data.length; i++){
streams.push(data.data[i].user_login);
}
//if cursor not empty recursively call getTwitch()
if(cursor !== '' && data.pagination !== null && test_BreakCase > 10){
getLiveStreams(cursor);
}
});
}
-尝试检查数组中的值
const s = await getLiveStreams().then(data => {
console.log(streams);
});
谢谢
我不是专家,但是当我开始尝试在函数调用完成之前将递归函数的输出存储在函数外部时,我通常会做错事。如果您将流数组传递给递归函数会怎么样?这也解决了我注意到的另一个可能的问题,即通常基本情况和递归情况都应该 return 某些东西,无论是最终结果还是另一个递归调用。我们一直 return 调用 getLiveStreams
直到最终数据数组被 return 编辑,这使调用堆栈向上冒泡到对递归函数的初始调用。
async function getLiveStreams(cursor = '', streams = []) {
//create query parameter for pagination and build into url
let query = cursor !== '' ? `after=${cursor}&` : ''
let baseURL = `https://api.twitch.tv/helix/streams?${query}first=100&language=en`
const data = await getTwitch(baseURL)
cursor = data.pagination.cursor
for (let i = 0; i < data.data.length; i++) {
streams.push(data.data[i].user_login)
}
// base case: cursor is empty
if (cursor === '' || data.pagination === null) {
return streams
}
// recursive case
return await getLiveStreams(cursor, streams)
}
编辑:递归情况下的 return 可能也应该是等待,因为函数 return 是一个承诺。
Edit2:我用 jsonplaceholder 稍微测试了你代码的这个 re-written 版本并且它有效:
const https = require('https')
const _URL = 'https://jsonplaceholder.typicode.com/posts/'
async function getTwitch(url) {
return new Promise((resolve, reject) => {
let data = ''
https.get(url, (res) => {
res.on('data', (chunk) => {
data += chunk
})
res.on('end', () => resolve(JSON.parse(data)))
})
})
}
async function getLiveStreams(i = 1, streams = []) {
let baseURL = _URL + i.toString()
const data = await getTwitch(baseURL)
streams.push(data)
// base case: we've made 50 requests
if (i === 50) {
return streams
}
// recursive case
return await getLiveStreams(i + 1, streams)
}
getLiveStreams().then(results => console.log(results))