使用Async / Await调用Async函数将值分配给对象中的键

时间:2019-03-04 10:43:41

标签: javascript object asynchronous ecmascript-6 async-await

我想知道如何使用Await / Async将值异步分配给多个不同的键。

最初我曾想过仅调用Async函数会分配如下值:

const getMetrics =  async (metric, key) => {
  const rawResponse = await fetch(`http:/localhost:8080/${metric}`, 
 {
    method: 'POST'
    body: JSON.stringify({
    projects:[
      {
        name: key
      }]
  }
)
  });

  return await rawResponse.json();
};

  const metrics =  {
    metric1:  {
      key1: getMetrics("metric1", "key1"),
      key2: getMetrics("metric1", "key2"),
      key3: getMetrics("metric1", "key3")
    },

    metric2: {
      key1: getMetrics("metric2", "key1"),
      key2: getMetrics("metric2", "key2"),
      key3: getMetrics("metric2", "key3")
    }
}

显然,这不是异步的工作方式,因为必须调用await才能从已解决的Promise中实际检索值。但是它确实异步检索并将值分配给键(尽管是promise而不是它们的值),这正是我想要的。

所以问题是我实际上如何异步获取分配给键的值?

  const metrics =  {
    metric1:  {
      key1: await getMetrics("metric1", "key1"),
      key2: await getMetrics("metric1", "key2"),
      key3: await getMetrics("metric1", "key3")
    },

    metric2: {
      key1: await getMetrics("metric2", "key1"),
      key2: await getMetrics("metric2", "key2"),
      key3: await getMetrics("metric2", "key3")
    }
}

我尝试了这一点,并且确实分配了值,但是显然这是完全违反直觉的,因为在那个时候它是同步顺序的。

通常只分配给异步函数的标准变量,我只是将函数调用添加到数组中,然后使用

将函数解构为变量
const asyncFunctions = [val1(), val2(), val3()];
const [key1,key2,key3] = await Promise.all(asyncFunctions);

如何为对象完成类似的事情?

4 个答案:

答案 0 :(得分:2)

使用与当前类似的方法来从Promise.all解构数组,然后将值重组成对象:

const promises = [getMetrics(), getMetrics(), getMetrics(), getMetrics(), getMetrics(), getMetrics()];
const [key1_1,key1_2,key1_3, key2_1, key2_2, key2_3] = await Promise.all(promises);
const metrics = {
  metric1: {
    key1: key1_1,
    key2: key1_2,
    key3: key1_3
  },
  metric1: {
    key1: key2_1,
    key2: key2_2,
    key3: key2_3,
  }
};

答案 1 :(得分:1)

有些库具有类似Promise.all的函数,但是可以使用对象属性而不是数组元素。例如,蓝鸟的Promise.props

const metrics = await Promise.props({
  metric1: Promise.props({
    key1: getMetrics(),
    key2: getMetrics(),
    key3: getMetrics()
  }),

  metric2: Promise.props({
    key1: getMetrics(),
    key2: getMetrics(),
    key3: getMetrics()
  })
})

如果您不需要所有的花哨功能,它就很容易实现。基本上,

if (!Promise.props) {
  Promise.props = async object => {
    let keys = Object.keys(object);
    let values = await Promise.all(Object.values(object));
    let result = {};
    for (let i = 0; i < keys.length; i++) {
      result[keys[i]] = values[i];
    }
    return result;
  }
}

答案 2 :(得分:0)

  

如何为对象完成类似的事情?

您使用Promise.all获取结果数组,然后将值复制出数组并复制到对象中。

答案 3 :(得分:0)

我认为async函数返回的是promise,而不是值。并且await必须在异步函数中。而且,您只能感觉像在异步函数中同步。

async function getVal(key){
    return await Promise.resolve(key)
}
let keys={}
async function getKeys(){
    keys={
        key1:await getVal("key1"),
        key2:await getVal("key2"),
        key3:await getVal("key3")
    }
    console.log(keys)
}
getKeys()