需要帮助相关的async函数执行流程(await,promises,node.js)

时间:2017-10-11 09:14:12

标签: javascript node.js asynchronous

如果您帮助我解决以下问题,我将不胜感激:

给定功能:

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) ());

我还使用以下代码表达.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请求' (为此我用console.log(' Pending ...')表达式添加了IF),我得到了损坏的结果:它包含所有的广告系列名称,ID,但没有图像数组。

    • [{" id":" 1111"," name":" some name"},{" id&# 34;:" 2222"," name":"其他名称"}], 虽然我在期待
    • [{" id":" 1111"," name":" some name"," images" :" URI"" URI" ...]} ...
  3. 我将非常感谢您的帮助:

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

    感谢。

1 个答案:

答案 0 :(得分:2)

使用全局变量allProductsInfo,然后触发多个异步使用它的并发函数,存在一个巨大的问题。这会创造各种竞争条件,你必须认为自己幸运你只有 而不是图像数据。

您可以通过使allProductsInfo成为局部变量,或者至少不使用它来存储来自getDataFromUrigetCpCampaignsIdsAndNamesData的中间结果来轻松解决此问题 - 使用不同的(本地!)变量对那些人来说。

但是,即使你这样做,你也可能会多次触发getAllProductsData,这不应该导致错误但仍然效率低下。在全局变量中存储承诺要容易得多,只需一次调用信息收集程序就可以初始化一次,并且每次都等待它 - 当它已经完成时将不会被注意到

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的作用。