【问题标题】:I need a Promise within a Promise and its .then to run first我需要一个 Promise 中的 Promise 及其 .then 先运行
【发布时间】:2021-03-08 10:00:55
【问题描述】:

所以,我正在阅读这个 XML 文件:

<GlDocumentInfo xmlns:opt="Opt.GL.Domain" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="Opt.GL.BusinessLogic">
  <world version="1.0.5">
    <GlDocument key="GlDocument:1">
        <GlDocumentNetwork>
            <Network key="Network:1">
                <Paths>
                    <Path key="Path:1" IsEmpty="False">
                        <PathNodes>
                            <PathNode key="PathNode:1" Node="Node:1" />
                            <PathNode key="PathNode:2" Node="Node:15" Distance="500" />
                            <PathNode key="PathNode:3" Node="Node:13" Distance="320" />
                            <PathNode key="PathNode:4" Node="Node:4" Distance="300" />
                            <PathNode key="PathNode:5" Node="Node:14" Distance="450" />
                        </PathNodes>
                    </Path>
                    <Path key="Path:2" IsEmpty="False">
                        <PathNodes>
                            <PathNode key="PathNode:5" Node="Node:14" />
                            <PathNode key="PathNode:6" Node="Node:4" Distance="450" />
                            <PathNode key="PathNode:7" Node="Node:13" Distance="300" />
                            <PathNode key="PathNode:8" Node="Node:15" Distance="320" />
                            <PathNode key="PathNode:9" Node="Node:1" Distance="500" />
                        </PathNodes>
                    </Path>
                </Paths>
               </Network>
       </GLDocument>
    </world>
</DocumentInfo>

路径是具有这种格式的模式:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var Path = new Schema({
    key: {type: String, unique: true},
    isEmpty: Boolean,
    pathNodes: [String]
});
module.exports = mongoose.model('Path', Path);

PathNode 是一个具有这种格式的模式:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var PathNode = new Schema({
    key: String,
    node: String,
    distance: Number
});
module.exports = mongoose.model('PathNode', PathNode);

所以我需要读取每个Path的每个PathNode,创建它们并将它们保存到数据库,以及将当前Path的那些PathNodes保存在一个数组中,然后创建路径并能够将数组分配给该路径的 pathNodes 属性,如您所见,该属性是这些 PathNodes 的字符串数组。 我的代码是:

var PathNode = require('../models/pathNode');
var Path = require('../models/path');
var repository = require('../../repository');

var jsonConverted = JSON.parse(convert.xml2json(req.file.buffer.toString(), { compact: true, spaces: 4, alwaysChildren: true }));
var pathNodesArray = [];

await Promise.all(jsonConverted.GlDocumentInfo.world.GlDocument.GlDocumentNetwork.Network.Paths.Path.map(async path => {

        pathNodesArray = [];
        await Promise.all(path.PathNodes.PathNode.map(async pathNode => {

            var newPathNode = new PathNode();
            newPathNode.key = pathNode._attributes.key;
            newPathNode.node = pathNode._attributes.Node; 
            newPathNode.duration = pathNode._attributes.Duration;
            newPathNode.distance = pathNode._attributes.Distance;

            pathNodesArray.push(newPathNode.key);

            repository.savePathNode(newPathNode);

        })).then(async () => {

            var newPath = new Path();
            newPath.key = path._attributes.key;
            newPath.isEmpty = path._attributes.IsEmpty.toString().toLowerCase();
            Object.assign(newPath.pathNodes, pathNodesArray);

            repository.savePath(newPath);
        });
    })).then(async () => {
(...) //doesn't matter for this question
}

读取工作正常,所有 PathNode 都被创建并保存在数据库中,问题是 Path:1Path:2 都被保存了使用相同的 PathNodes 列表,Path:1 具有来自 Path:2 的 PathNodes 列表。因此,外部 Promise 中的 Promise.then 无法正常工作,因为它正在读取所有 PathNode,然后才读取 Path,并分配最后组装的数组PathNodes 到最后一个 Path。

你能帮我解决这个问题,所以每个 Path 都有其对应的 PathNodes 吗?我试过从多个地方删除 asyncawait 保存... 谢谢。

【问题讨论】:

  • 不要使用.then(async () =&gt; {。你已经在 await 执行承诺,只需将代码放在 await 语句之后,而不是在 then 回调中。
  • 您使用了非常混乱的async/awaitthen() 组合。如果你只是坚持一个或另一个,这将更容易阅读
  • @Bergi 我就是这样做的,但是,它在两个路径中保存了相同的路径节点。绝望在这一点上是真实的:c

标签: javascript node.js promise async-await es6-promise


【解决方案1】:

尝试在repository.savePathNode(newPathNode) 之前添加return。 现在,它接缝,你的嵌套承诺没有等待

...
await Promise.all(path.PathNodes.PathNode.map(async pathNode => {

            var newPathNode = new PathNode();
            newPathNode.key = pathNode._attributes.key;
            newPathNode.node = pathNode._attributes.Node; 
            newPathNode.duration = pathNode._attributes.Duration;
            newPathNode.distance = pathNode._attributes.Distance;

            pathNodesArray.push(newPathNode.key);

            return repository.savePathNode(newPathNode);

        }))
...

【讨论】:

  • 谢谢你的回复,但是,我应该返回什么?因为 repository.savePathNode(newPathNode); 之前的空返回会将其变灰并且永远不会到达此语句
【解决方案2】:

除了@Yevhenii 提到的问题外,您的var pathNodesArray = []; 范围不正确。您希望每条路径都有自己的路径节点数组,并且在循环中执行 pathNodesArray = []; 时,如果它是顺序的,它可能会起作用,但在并行处理路径时会失败。更喜欢const 而不是var

const PathNode = require('../models/pathNode');
const Path = require('../models/path');
const repository = require('../../repository');

const jsonConverted = JSON.parse(convert.xml2json(req.file.buffer.toString(), { compact: true, spaces: 4, alwaysChildren: true }));
const paths = jsonConverted.GlDocumentInfo.world.GlDocument.GlDocumentNetwork.Network.Paths.Path;
await Promise.all(paths.map(async path => {
    const pathNodesArray = [];
//  ^^^^^ declare inside each iteration
    await Promise.all(path.PathNodes.PathNode.map(async pathNode => {
        const newPathNode = new PathNode({
            key: pathNode._attributes.key,
            node: pathNode._attributes.Node,
            duration: pathNode._attributes.Duration,
            distance: pathNode._attributes.Distance,
        });
        pathNodesArray.push(newPathNode.key);

        await repository.savePathNode(newPathNode);
//      ^^^^^
    }));

    const newPath = new Path({
        key: path._attributes.key,
        isEmpty: path._attributes.IsEmpty.toString().toLowerCase(),
        pathNodes: pathNodesArray,
    });

    await repository.savePath(newPath);
//  ^^^^^
}));
// … doesn't matter for this question

【讨论】:

  • 谢谢Bergi,这对您有帮助!度过美好的一天
猜你喜欢
  • 2017-07-31
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
相关资源
最近更新 更多