【问题标题】:Building an object with multiple async/await calls使用多个 async/await 调用构建对象
【发布时间】:2019-02-04 12:29:07
【问题描述】:

我正在使用一个在两个端点上有数据的 api:

  • /news 为我提供包含少量属性的文章列表
  • /news/{id}/metadata 获取文章的所有属性

我实际上需要获取所有属性,并且我计划构建一个主对象来驱动我的 UI。

当前功能:

  • getNews:一个 async/await 函数,成功从 /news 获取文章列表
  • getMetaPerArticle:另一个异步/等待函数,它接受一个 ID 并调用 /news/{id}/metadata

行为:

  • 我运行 getNews 异步函数并等待响应
  • 当响应通过时,我映射响应数组并对数组中的每个项目运行 getMetadata 函数
  • getMetadata 完成后,将结果存储到常量中,并分配给 element.metadata

问题: - 我的两个函数都解析,但我的最终对象包含 Promise.resolve 对象。对象具有正确的值。

代码

const getNews = async options => {
    try {
      const { data } = await axios(options);
      const parsedEnDataWithMeta = parsedEnData.map(article => {
        const mergedArticleWithMeta = {
          ...article,
          ...getMetaPerArticle(article.id)
        };
        return mergedArticleWithMeta;
      });
    } catch (getNewsError) {
      dispatch(receiveNewsError(getNewsError));
    }
  };



const getMetaPerArticle = async articleID => {
    const axiosOptions = {
      method: "GET",
      url: `url`,
    };
    try {
      const response = await axios(axiosOptions);
      return response.data;
    } catch (err) {
      console.error(err);
      dispatch(receiveNewsError(err));
    }
  };

输出

(6) [{…}, {…}, {…}, {…}, {…}, {…}]
0: {
    abstract: "",
    ...
    metadata: Promise {<resolved>: {...}}
}

【问题讨论】:

    标签: javascript async-await


    【解决方案1】:

    getMetaPerArticle 返回一个promise,因此在尝试映射到parsedEnDataWithMeta 之前,您需要等待这些promise 解决。像这样的:

    const getNews = async options => {
      try {
        const { data } = await axios(options);
        const metadataPromises = data.map(article => getMetaPerArticle(article.id));
        const metadata = await Promise.all(metadataPromises);
        const parsedEnDataWithMeta = data.map((article, i) => ({
          ...article,
          ...metadata[i]
        });
      } catch (getNewsError) {
        dispatch(receiveNewsError(getNewsError));
      }
    };
    

    【讨论】:

    • 感谢您的帮助!这真的让我感到困惑,我在 getMetaPerArticle 中尝试了 Promise.resolve 但仍然返回了一个承诺,我想这是因为 async/await 包装器。 getNews 中的 Promise.all() 很有效。 ?
    • 是的,异步函数总是返回一个承诺。而Promise.resolve 是创建承诺的快捷方式,该承诺立即进入“已解决”状态。
    【解决方案2】:

    你的问题是getMetaPerArticle返回一个Promise,所以你需要在它的前面添加一个await,并将箭头函数标记为async

    const parsedEnDataWithMeta = parsedEnData.map(async article => {
      const mergedArticleWithMeta = {
        ...article,
        ...await getMetaPerArticle(article.id)
      };
      return mergedArticleWithMeta;
    });
    

    之后parsedEnDataWithMeta 将保存一个 Promise 列表,因此您需要等到使用Promise.all 解决所有问题:

    const parsedEnDataWithMeta = await Promise.all(parsedEnData.map(async article => {
      const mergedArticleWithMeta = {
        ...article,
        ...await getMetaPerArticle(article.id)
      };
      return mergedArticleWithMeta;
    }));
    

    如果您需要更频繁地使用它,那么您可以定义一个处理 Promise 的 map 函数:

    function promiseMap( array, callback ) {
      return Promise.all(array.map(callback))
    }
    
    
    const parsedEnDataWithMeta = await promiseMap(parsedEnData, async article => {
      const mergedArticleWithMeta = {
        ...article,
        ...await getMetaPerArticle(article.id)
      };
      return mergedArticleWithMeta;
    });
    

    【讨论】:

      猜你喜欢
      • 2020-06-22
      • 1970-01-01
      • 2021-01-20
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多