异步/等待函数中的 JavaScript Promise 解析最终的响应数组 [英] JavaScript Promise inside async/await function resolve final array of responses

查看:62
本文介绍了异步/等待函数中的 JavaScript Promise 解析最终的响应数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 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 array output which contains the results (values not state) of all the promises. At least, when I execute it, and check for my sanity checks with the console.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 调用也返回 Promises).

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 Promises 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 将导致 Promiserejected 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆