【问题标题】:How to nest promises (Promise.all inside Promise.all)如何嵌套 Promise(Promise.all 内的 Promise.all)
【发布时间】:2020-01-23 16:31:00
【问题描述】:

考虑以下嵌套Promises的结构:

const getData = async() => {

  const refs = [{
      name: "John33",
      age: 33
    },
    {
      name: "John34",
      age: 34
    },
    {
      name: "John35",
      age: 35
    },
    {
      name: "John36",
      age: 36
    }
  ];


  let source = [{
      name: "John30",
      age: "unknown"
    },
    {
      name: "John31",
      age: "unknown"
    },
    {
      name: "John32",
      age: "unknown"
    },
    {
      name: "John33",
      age: "unknown"
    },
    {
      name: "John34",
      age: "unknown"
    },
    {
      name: "John35",
      age: "unknown"
    }, {
      name: "John36",
      age: "unknown"
    },
    {
      name: "John37",
      age: "unknown"
    },
    {
      name: "John38",
      age: "unknown"
    },
    {
      name: "John39",
      age: "unknown"
    }
  ];

  const resolver = doc => {
    return new Promise(doc => {
      let clone = { ...doc
      };
      let found = refs.find(ref => {
        return ref.name === doc.name;
      });

      if (found) clone.age = found.age;
      return clone;
    });
  };

  let getRefs = (doc, refs) => {
    const promises = refs.map(r => {
      resolver(doc).then(result => {
        return result;
      });
    });

    return Promise.all(promises);
  };


  let getCursorData = (cursor, refs, data) => {
    const promises = cursor.forEach(doc => {
      console.log("Getting cursor for " + doc.name);
      let clone = { ...doc
      };

      return getRefs(clone, refs).then(result => {
        console.log("Getting refs for " + clone.name);
        data.push(result);
      });
      return;
    });

    return Promise.all(promises);
  };

  // Get data
  let data = [];
  await getCursorData(source, refs, data);

  console.log("Returned data: ");
  console.log(data);

  return data;
};

console.log("Begin");
getData().then(result => {
  console.log("End");
  console.log(result)
});

由于某种原因,我没有到达代码的末尾(End 没有被打印出来)。我怀疑有一些位置或缺少返回,但我没有找到解决方案。

我怎样才能使这个代码结构按预期工作,如下:

  1. 遍历源(我的数据来自数据库
  2. 对于每个寄存器,应用引用更改(在示例中更改 age)
  3. 返回固定引用的数据

此代码的预期结果是使用当前的承诺结构获取原始数据 (source) 并修复了可用的引用:

[
      name: "John30",
      age: "unknown"
    },
    {
      name: "John31",
      age: "unknown"
    },
    {
      name: "John32",
      age: "unknown"
    },
    {
      name: "John33",
      age: 33
    },
    {
      name: "John34",
      age: 34
    },
    {
      name: "John35",
      age: 35
    }, {
      name: "John36",
      age: 36
    },
    {
      name: "John37",
      age: "unknown"
    },
    {
      name: "John38",
      age: "unknown"
    },
    {
      name: "John39",
      age: "unknown"
    }
]

【问题讨论】:

  • 我看到End 打印出来了,尽管它打印在所有Getting refs... 行中间的某个地方。也许问题是你需要awaitthen 打电话给getData
  • 你确定。修复了代码,使其表现得像我原来的错误......
  • new Promise() 将一个函数作为参数,该函数将resolve(和reject)函数作为参数,而不是doc。这没有任何意义。
  • 缺少什么解释?
  • 我相信,当你应该在 getCursorData 中使用 map 时,你正在使用 forEach。如果你修复它,你会坚持到底,但你会得到一堆undefined 的数组。这是您的预期结果吗?

标签: javascript promise es6-promise


【解决方案1】:

给你!

const SimulatedDatabaseCall = new Promise(resolve => {
	setTimeout(() => {
		resolve([
			{
				name: 'John33',
				age: 33
			},
			{
				name: 'John34',
				age: 34
			},
			{
				name: 'John35',
				age: 35
			},
			{
				name: 'John36',
				age: 36
			}
		]);
	}, 200);
});

let source = [
	{
		name: 'John30',
		age: 'unknown'
	},
	{
		name: 'John31',
		age: 'unknown'
	},
	{
		name: 'John32',
		age: 'unknown'
	},
	{
		name: 'John33',
		age: 'unknown'
	},
	{
		name: 'John34',
		age: 'unknown'
	},
	{
		name: 'John35',
		age: 'unknown'
	},
	{
		name: 'John36',
		age: 'unknown'
	},
	{
		name: 'John37',
		age: 'unknown'
	},
	{
		name: 'John38',
		age: 'unknown'
	},
	{
		name: 'John39',
		age: 'unknown'
	}
];

async function updateSource(source, SimulatedDatabaseCall) {
	await SimulatedDatabaseCall;
	SimulatedDatabaseCall.then(_database => {
		var sourceMap = source.map(_sourceOBJ => {
			return _sourceOBJ.name;
		});
		_database.forEach(_databaseOBJ => {
			var index = sourceMap.indexOf(_databaseOBJ.name);
			source[index].age = _databaseOBJ.age;
		});
	});

	return source;
}

updateSource(source, SimulatedDatabaseCall).then(_val => {
	console.log(_val);
});

【讨论】:

  • SimulatedDatabaseCall 应该是每个项目一个,而不是每个项目一个...
  • 我的意思是,如果像 Mendes 所说的那样调整为每个项目一次,这应该可以工作,但这不会帮助他了解他的原始代码存在什么问题。他的原始逻辑没有问题,他只是没有将数据正确地放入 Promise 对象中。
猜你喜欢
  • 2016-11-20
  • 1970-01-01
  • 2018-12-02
  • 1970-01-01
  • 2020-02-08
  • 2020-08-06
  • 2019-03-30
  • 1970-01-01
相关资源
最近更新 更多