异步/等待函数中的 JavaScript Promise 解析最终的响应数组 [英] JavaScript Promise inside async/await function resolve final array of responses
问题描述
我是 JavaScript 和 Promises 的新手.我正在尝试构建从 API 获取的对象数组.
I'm quite a newbie in JavaScript and in Promises. I'm trying to build an array of objects that I get from an API.
为此,我在文件 MyFile.js
中构建了两个函数.
To do so, I've build two functions in a file MyFile.js
.
第一个在 axios 承诺被解决时返回一个承诺.这是
The first one returns a promise when an axios promise is resolved. It's
function get_items (url) {
return new Promise((resolve, reject) => {
let options = {
baseURL: url,
method: 'get'
}
axios(options)
.then(response => {
resolve(response.data)
})
.catch(error => {
reject(error.stack)
})
})
}
第二个看起来像这样:
let output = []
let next_url = 'https://some_url.com/api/data'
async function get_data () {
try {
let promise = new Promise((resolve, reject) => {
if (next_url) {
get_items(next_url)
.then(response => {
output.push(...response.results)
if (response.next) {
next_url = response.next
console.log('NEXT_URL HERE', next_url)
get_data()
} else {
console.log('else')
next_url = false
get_data()
}
})
.catch(error => {
reject(error.stack)
})
} else {
console.log('before resolve')
resolve(output)
}
})
return await promise
} catch(e) {
console.log(e)
}
}
这是我磨牙的地方.我想我对这个功能的理解是:
It's where I'm grinding my teeth. What I think I understand of this function, is that:
- 它返回一个 promise 的值(这就是我理解的
return await promise
正在做的) - 这是一个递归函数.因此,如果有 next_url,则该函数继续执行.但是如果没有,它最后一次被调用进入
else
部分,在那里它解析数组output
,其中包含所有的结果(值不是状态)承诺.至少,当我执行它并使用我编写的console.log
检查我的健全性检查时,它可以工作.
- it's returning the value of a promise (that's what I understand
return await promise
is doing) - it's a recursive function. So, if there is a next_url, the function continues on. But if there is not, it gets called one last time to go into the
else
part where it resolves the arrayoutput
which contains the results (values not state) of all the promises. At least, when I execute it, and check for my sanity checks with theconsole.log
I wrote, it works.
所以,output
充满了数据,这很棒.
So, output
is filled with data and that's great.
但是,当我从另一个文件 MyOtherFile.js
调用此函数时,如下所示:
But, when I call this function from another file MyOtherFile.js
, like this:
final_output = []
MyFile.get_data()
.then(result => {
console.log('getting data')
final_output.push(...result)
})
它永远不会进入 then
部分.当我 console.log MyFile.get_data()
时,这是一个未决的承诺.
it never gets into the then
part. And when I console.log MyFile.get_data()
, it's a pending promise.
所以,我想做的是能够让 get_data()
等待所有的承诺结果(不使用 Promise.all(),以串行方式调用,而不是在并行,我猜这对表演来说会很棒?)然后能够在从其他任何地方调用此函数时在 then
部分检索该响应.请记住,总的来说,我是 Promise 和 JavaScript 的新手(我更像是一个 Python 人).
So, what I would like to do, is be able to make get_data()
wait for all the promises result (without using Promise.all(), to have calls in serie, not in parallel, that would be great for performances, I guess?) and then be able to retrieve that response in the then
part when calling this function from anywhere else.
Keep in mind that I'm really a newbie in promises and JavaScript in general (I'm more of a Python guy).
如果我的问题不够清楚,请告诉我.我这两天一直在挠头,感觉就像在兜圈子一样.
Let me know if my question isn't clear enough. I've been scratching my head for two days now and it feels like I'm running in circle.
感谢您成为一个很棒的社区!
Thanks for being an awesome community!
推荐答案
有几个问题.一个是你永远不会resolve
初始的Promise
,除非进入else
块.另一个是你应该每次返回递归的get_data
调用,这样它就可以与初始的Promise
正确链接.您也可以考虑避免 显式承诺构造反模式 - get_items
已经返回了一个 Promise
,所以没有必要再构造一个(get_items
内部也一样>、axios
调用也返回 Promise
s).
There are a few problems. One is that you never resolve
the initial Promise
unless the else
block is entered. Another is that you should return the recursive get_data
call every time, so that it can be properly chained with the initial Promise
. You may also consider avoiding the explicit promise construction antipattern - get_items
already returns a Promise
, so there's no need to construct another one (same for the inside of get_items
, axios
calls return Promise
s too).
你可能会考虑一个普通的 while
循环,重新分配 next_url
字符串直到它是假的:
You might consider a plain while
loop, reassigning the next_url
string until it's falsey:
function get_items (baseURL) {
const options = {
baseURL: url,
method: 'get'
}
// return the axios call, handle errors in the consumer instead:
return axios(options)
.then(res => res.data)
}
async function get_data() {
const output = []
let next_url = 'https://some_url.com/api/data'
try {
while (next_url) {
const response = await get_items(next_url);
output.push(...response.results)
next_url = response.next;
}
} catch (e) {
// handle errors *here*, perhaps
console.log(e)
}
return output;
}
请注意,.catch
将导致 Promise
从 rejected Promise
转换为 resolved 一个 - 你不想 .catch
到处都是,因为这会让调用者很难检测到错误.
Note that .catch
will result in a Promise
being converted from a rejected Promise
to a resolved one - you don't want to .catch
everywhere, because that will make it difficult for the caller to detect errors.
这篇关于异步/等待函数中的 JavaScript Promise 解析最终的响应数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!