我需要 Promise 中的 Promise 及其 .then 首先到 运行

I need a Promise within a Promise and its .then to run first

所以,我正在阅读这个 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,创建它们并将它们保存到数据库,以及保存那些 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
}

读取工作正常,正在创建所有 PathNodes 并将其保存在数据库中,问题是 Path:1Path:2 两者都使用相同的 PathNodes 列表保存,Path:1 具有来自 Path:2 的 PathNodes 列表。所以这个 Promise.then 里面的 outter Promise 不能正常工作,因为它正在读取所有 PathNodes,然后才读取路径,并且将最后组装的 PathNodes 数组分配给最后一个 Path。

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

尝试在 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);

        }))
...

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

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