如何进行嵌套结构的映射异步转换?

时间:2019-02-08 03:54:40

标签: javascript async-await

说我有一些看起来像这样的代码:

const myObject = {
   outerList : [
      {
         innerList: [
            1, 2, 3
         ]
      }, 
      {
         innerList: [
            2, 4, 6
         ]
      }
   ]
}; 

async function asyncTransform(i) {  
    return new Promise((resolve) => {
      setTimeout(() => {
          resolve(i+1); 
      }, Math.random()* 1000); 
    }); 
}

async function asyncTransformNestedObject(obj) {
   //??? 
}

asyncTransformNestedObject(myObject).then((result) => {
    console.log(result);
}); 

我想将对象转换为此:

{
   outerList : [
      {
         innerList: [
            2, 3, 4
         ]
      }, 
      {
         innerList: [
            3, 5, 7
         ]
      }
   ]
}; 

实现此目的的最佳方法是什么-理想情况下,异步函数同时运行。

3 个答案:

答案 0 :(得分:1)

  • Array.map将每个内部元素传递给asyncTransform返回的Promise,然后将该数组传递给Promise.all
  • 然后在步骤1中创建的每个Promise.all Promise.all

这是一个例子:

const myObject = {
  outerList : [
    {
      innerList: [
        1, 2, 3
      ]
    }, 
    {
      innerList: [
        2, 4, 6
      ]
    }
  ]
}

function asyncTransform(i) {
  return new Promise(resolve => setTimeout(() => resolve(i + 1), 50))
}

function asyncTransformNestedObject(obj) {    
  const innerLists = obj.outerList.map(el => {
    return Promise.all(el.innerList.map(asyncTransform))
      .then(results => el.innerList = results)
  })
  
  return Promise.all(innerLists)
    .then((results, i) => obj.outerList.map((el, i) => ({ 
        ...el, 
        innerList: results[i] 
      })))
}


asyncTransformNestedObject(myObject).then((result) => {
  console.log(result)
})

答案 1 :(得分:0)

这是我最终得到的解决方案:

考虑起来很简单:

Promise.all的Promise.all将在所有承诺的最大时间解决。

const myObject = {
   outerList : [
      {
         innerList: [
            1, 2, 3
         ]
      }, 
      {
         innerList: [
            2, 4, 6
         ]
      }
   ]
}; 

async function asyncTransform(i) {  
    return new Promise((resolve) => {
      setTimeout(() => {
          resolve(i+1); 
      }, Math.random()* 1000); 
    }); 
}

async function transformInnerObj(innerObj) {    
    const newInnerList = await Promise.all(innerObj.innerList.map(i => asyncTransform(i))); 
    return {
      innerList: newInnerList
    }; 
}

async function asyncTransformNestedObject(obj) {
   
   const newOuterList = await Promise.all(obj.outerList.map(innerObj =>       transformInnerObj(innerObj)));                                           
   return {
      outerList:  newOuterList                                  
   }; 
}

asyncTransformNestedObject(myObject).then(result => {
    console.log(result);
});

答案 2 :(得分:0)

我会在ES5中使用递归setTimeout / requestAnimationFrame解决此问题,但是如果您坚持使用异步功能,这似乎可以解决问题:

     async function convert(arr,i = 0){
            if(!arr[i]){return arr}
            await arr[i].innerList.reduce((ac,d,i,a) => ++a[i],(async function(){}()));
            return convert(arr,++i);
        }

    convert(myObject.outerList);

//myObject
    "[
        {
            "innerList": [
                2,
                3,
                4
            ]
        },
        {
            "innerList": [
                3,
                5,
                7
            ]
        }
    ]"

您没有指定任何有关更改原始对象的内容,因此我将其更改为适当的位置。我还返回了innerArray,您可能已经返回了对象本身的指令,并使用await存储在变量中。