所以,我正在读取这个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>
Path是一个具有以下格式的模式:
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,创建它们并将它们保存到DB,以及将当前路径的那些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都被创建并保存在DB中,问题是Path:1和Path:2都使用相同的PathNodes列表保存,Path:1具有Path:2中的PathNode列表。所以这个Promise和.然后outter Promise内部的不能正常工作,因为它正在读取所有路径节点,然后它才读取路径,并将最后一个组装的路径节点数组分配给最后一个路径。
你能帮我解决这个问题吗,这样每个路径都有相应的PathNodes?我已经尝试从多个位置删除异步,等待保存。。。非常感谢。
除了@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
尝试在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);
}))
...