繁体   English   中英

需要帮助相关的异步功能执行流程(等待,承诺,node.js)

[英]Need help related async functions execution flow (await, promises, node.js)

如果您在以下情况下为我提供帮助,我们将不胜感激:

给定功能:

async function getAllProductsData() {
  try {
    allProductsInfo = await getDataFromUri(cpCampaignsLink);
    allProductsInfo = await getCpCampaignsIdsAndNamesData(allProductsInfo);
    await Promise.all(allProductsInfo.map(async (item) => {
      item.images = await getProductsOfCampaign(item.id);
    }));
    allProductsInfo = JSON.stringify(allProductsInfo);
    console.log(allProductsInfo);
    return allProductsInfo;
  } catch(err) {
    handleErr(err);
  }
}

启动服务器时将触发该函数,并从其他站点收集活动信息:获取数据(getDataFromUri()),然后从数据名称和id中提取(getCpCampaignsIdsAndNamesData()),然后获取每个活动的产品图片(getProductsOfCampaign()) ;

我也有express.app和以下代码:

app.get('/products', async (req, res) => {
  if (allProductsInfo.length === undefined) {
    console.log('Pending...');
    allProductsInfo = await getAllProductsData();
  }
  res.status(200).send(allProductsInfo);
});

问题描述:

  1. 启动服务器,等待几秒钟,直到执行getAllProductsData(),执行'/ products'GET请求,一切正常!
  2. 启动服务器并立即启动'/ products'GET request(为此目的,我在console.log('Pending ...')表达式中添加了IF),但结果却遭到破坏:它包含所有广告系列的名称,ID,但没有图片数组。

    • [{{id“:” 1111“,” name“:”某些名称“},{” id“:” 2222“,” name“:”某些其他名称“}]]
    • [{“ id”:“ 1111”,“名称”:“某些名称”,“图像”:[“ URI”,“ URI” ...]} ...]

非常感谢您的帮助:

  • 解释异步执行情况的流程,以及为什么不等待将图像数组添加到对象而发送结果的原因?
  • 如果您知道涉及我的主题的一些有用的文章/规格部分,我将非常感谢。

谢谢。

使用全局变量allProductsInfo ,然后触发多个异步使用它的并发函数,这是一个巨大的问题。 这会产生各种竞赛条件,并且您必须幸运地得到自己只有图像数据。

您可以通过将allProductsInfo为局部变量来轻松解决此问题,或者至少不使用它来存储getDataFromUrigetCpCampaignsIdsAndNamesData的中间结果-为它们使用不同的(局部!)变量。

但是,即使这样做,也可能getAllProductsData多次触发getAllProductsData ,这不会导致错误,但效率仍然很低。 将promise存储在全局变量中很容易,只需一次调用信息收集过程即可将其初始化一次 ,并且每次都等待它-当它已经实现时就不会被注意到。

async function getAllProductsData() {
  const data = await getDataFromUri(cpCampaignsLink);
  const allProductsInfo = await getCpCampaignsIdsAndNamesData(allProductsInfo);
  await Promise.all(allProductsInfo.map(async (item) => {
    item.images = await getProductsOfCampaign(item.id);
  }));
  console.log(allProductsInfo);
  return JSON.stringify(allProductsInfo);
}

const productDataPromise = getAllProductsData();
productDataPromise.catch(handleErr);
app.get('/products', async (req, res) => {
  res.status(200).send(await productDataPromise);
});

当然,您可能还希望仅在数据加载后启动服务器(或向其添加/products路由),并在此之前仅提供状态500。 另外,您还应该考虑在拒绝承诺后点击路由时会发生什么-不确定handleErr做什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM