Promise数组,传递创建中使用的变量

时间:2017-08-17 13:51:06

标签: javascript express promise

使用Express,我使用.map创建一个API调用数组,我希望将其结果组合成一个响应对象。由于每个调用使用不同的查询参数,我想使用查询参数作为响应对象的键。

我使用axios创建GET请求,它返回一个promise,然后我使用axios.all等待所有的promises解析。

问题是在承诺解决后,我不再能够访问用于创建它们的变量。如何将这些变量附加到承诺中供以后参考?

以下是API:

router.get('/api', (req, res) => {
  const number = req.query.number;
  res.json({ content: "Result for " + number });
});

以下是我尝试合并结果的地方:

router.get('/array', async (req, res) => {
  res.locals.payload = {};
  const arr = [1, 2, 3, 4, 5];
  const promises = arr.map(number => {
    return axiosInstance.get('/api', { params: { number: number } })
  });
  const results = await axios.all(promises);
  results.map(r => {
    // number should match original, but I no longer have
    // access to the original variable
    number = 1;
    res.locals.payload[number] = r.data;
  });
  res.json(res.locals.payload);
});

GET on / array的结果:

{
    "1": {
        "content": "Result for 5"
    }
}

创建Promise对象以保存密钥时,我该怎么办?

1 个答案:

答案 0 :(得分:0)

如果结果将是一个基于0的索引而不是具有属性“1”,“2”等的对象的数组,我们可以使用Promise.all(或{{1}如果它提供相同的保证axios.all它给你的数组将按照你给它的承诺的顺序,无论它们解决的顺序如何)。但我猜你的“数字”实际上是一个更有趣的占位符。 : - )

您可以通过使用promise是管道这一事实来实现这一点,其中各种处理程序在此过程中转换内容。

在这种情况下,您可以将Promise.all调用的结果转换为具有数字和结果的对象:

get

现在,const promises = arr.map(number => { return axiosInstance.get('/api', { params: { number } }) .then(result => ({result, number})); }); 回调中的results会收到一系列具有all.thenresult属性的对象。如果您愿意,可以使用解构参数在number回调中接收它们:

results.map

直播示例:

//           vvvvvvvvvvvvvvvv---------------- destructuring parameters
results.map(({result, number}) => {
  res.locals.payload[number] = result.data;
//                   ^^^^^^----^^^^^^-------- using them
});

注意我上面使用了ES2015 +属性简写,因为你正在使用箭头功能等。对象初始值设定项// Fake axiosInstance const axiosInstance = { get(url, options) { return new Promise(resolve => { setTimeout(() => { resolve({data: `Data for #${options.params.number}`}); }, 300 + Math.floor(Math.random() * 500)); }); } }; // Fake axios.all: const axios = { all: Promise.all.bind(Promise) }; // Fake router.get callback: async function routerGet() { const payload = {}; // stand-in for res.locals.payload const arr = [1, 2, 3, 4, 5]; const promises = arr.map( number => axiosInstance.get('/api', { params: { number } }) .then(result => ({result, number})) ); const results = await axios.all(promises); results.map(({result, number}) => { /*res.locals.*/payload[number] = result.data; }); console.log(/*res.locals.*/payload); } // Test it routerGet().catch(e => { console.error(e); });{ number }完全相同。

附注2:如果您愿意,可以使用简明的箭头函数进行{ number: number }回调:

map
相关问题