如何使用带有 Promise.all 的 AsyncData 从多个 api 的工作客户端获取数据但导致 nginx 为 504

Posted

技术标签:

【中文标题】如何使用带有 Promise.all 的 AsyncData 从多个 api 的工作客户端获取数据但导致 nginx 为 504【英文标题】:How to use AsyncData with Promise.all to get data from multiple api's works client side but causes nginx to 504 【发布时间】:2020-02-08 04:03:12 【问题描述】:

我目前正在转换一个 vue 应用程序以使用 NUXT 框架。为我的应用程序添加对 s-s-r 的支持,并在尝试将 asyncData 与单个页面上的多个数据源一起使用时遇到了以下问题。

我正在尝试设置 asyncData 以从页面工作所需的 2 个独立数据源获取数据。现在,当 Promise.all 解析它获取两组数据时,代码在客户端工作。但是,在服务器端,当 console.log 时,promise 都处于挂起状态并导致 nginx 超时并给出 504 bad gateway 错误。

我试图让这个工作使用 async/await 和 promise.all 无济于事。请参阅下面的代码示例。

导入函数 getData 和 getJsonFile 都使用 Axios 并返回带有数据对象的已解决承诺。

// Using async/await
export default 
  async asyncData(context) 
    const nameData = await getData('getInformationByNames', 
      names: [context.params.name],
      referingPage: `https://local.test.com$context.route.fullPath`
    );

    const content = await getJsonFile(
      `/data/pages/user/$context.params.id`
    );

    return 
      names: nameData,
      content
    ;
  

// Using Promise.all
export default 
  async asyncData(context) 
    const [nameData, content] = await Promise.all([
      getData('getInformationByNames', 
        names: [context.params.name],
        referingPage: `https://local.test.com$context.route.fullPath`
      ),
      getJsonFile(`/data/pages/user/$context.params.id`)
    ]);
    return 
      names: nameData,
      content
    ;
  

// getJsonFile

import axios from 'axios';
import replaceStringTokens from '@/scripts/helpers/replaceStringTokens';

export default function getJsonFile(path, redirect = true) 
  const jsonFilePath = `$path.json`;

  return axios.get(jsonFilePath).then((response) => 
    if (typeof response.data === 'object') 
      return replaceStringTokens(response.data);
    
    return false;
  );

// getData

import axios from 'axios';
import getUserDevice from '@/scripts/helpers/getUserDevice';

// require php-serialize node package to serialize the data like PHP would for the api endpoint.
const Serialize = require('php-serialize');

export default function getData(action, data) 
  const dataApiAddress = '/api/getData.php';

  const dataToPass = data || ;
  // all actions available on the api will need to know the users device so add it to the data.
  dataToPass.userDevice = getUserDevice();

  // package the data like the api expects to receive it
  const serializedAndEncodedData = encodeURIComponent(
    Serialize.serialize(dataToPass)
  );

  const axiosParams = 
    action,
    data: serializedAndEncodedData
  ;

  return axios
    .get(dataApiAddress, 
      params: axiosParams
    )
    .then((response) => 
      return response.data.data;
    )
    .catch((error) => 
      console.log(error);
      return false;
    );


我希望承诺能够解决,并且两组数据都返回一个可供页面在客户端和服务器端使用的可用数据。

有没有更好的方法来获取多组数据或调试服务器端,以便我可以看到是什么导致承诺无法在服务器上解析?

【问题讨论】:

请发布getData()函数和getJsonFile()函数 更新帖子以包含这两个功能 你设置了 axios baseurl 吗?您可能正在查询服务器上的本地主机 我刚刚写了一些类似于你的 async/await 测试函数(// 使用 async/await ...),我得到:jsfiddle.net/zvtde613/1 如果你有 504 错误,如果我们没有查看服务器端的 sode 很难看出有什么问题。你的/api/getData.php 里有什么? 很遗憾,由于法律原因,我无法共享服务器端代码。感谢您花时间查看我将尝试调整您共享的 jsfiddle 以使其在没有函数的情况下工作,然后一旦工作将代码抽象回函数。 Aldarund 这就是我将在我的 nuxt 配置中为 Axios 设置一个基本 URL 的建议,看看这是否能解决我的问题 【参考方案1】:

修复了在 API 上查询的数据存在一些差异的问题。数据库中的数据在开始时使用了一个大写字母,这一定是输入错误。因此,由于 API 发送小写版本的查询,这导致 promise 无法解析,进而导致 Nginx 超时。

【讨论】:

以上是关于如何使用带有 Promise.all 的 AsyncData 从多个 api 的工作客户端获取数据但导致 nginx 为 504的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 像 Java 8 上的“Promise.all”(可能带有 lambdas)

带有嵌套地图的 Promise.all .. 第一张地图仅适用于其他人在猫鼬中返回空对象

如何在 Nuxt 的 asyncData 中对 Promise.all 进行数组解构

如何使用并区分Promise.all和Promise.race?

理解Promise.all,Promise.all与Promise.race的区别,如何让Promise.all在rejected后依然返回resolved状态

如何返回 Promise.all 获取 api json 数据?