我有一个托管JSON对象数组的文件。我想将这些对象插入数据库。插入是一个异步命令,大约需要一秒钟才能执行。该脚本应提供插入记录的计数。创建了以下内容以模拟该问题:
const fs = require('fs');
const jstream = require('JSONStream');
new Promise((res, rej) => {
let rec = 0;
try {
const stream = fs.createReadStream('./sample.json');
console.log(1);
const p = stream.pipe(jstream.parse('*'))
p.on('data', (stuff) => {
console.log(2);
console.log("New Round");
console.log(stuff);
// Simulated database insert
setTimeout(()=> rec++, 2000 );
});
p.on('end', (rec) => {
console.log(3);
res(rec);
});
p.on('error', (err) => {
console.log(4);
rej(err);
})
} catch (err) {
console.log(5);
rej(err);
}
})
.then((count) => {
console.log(6);
console.log(count);
console.log("Done loading!");
})
.catch((err) => {
console.log(7);
console.log(err);
});
运行脚本时,我没有得到总计。以下是我得到的输出:
1
2
New Round
{ _id: '15fb781a-d2fc-4429-82c7-8eb3e0a007b7', _name: 'bruce' }
2
New Round
{ _id: '02007ad3-2b25-46d9-a609-edacf9e151dc', _name: 'ken' }
2
New Round
{ _id: '18913a7a-18e6-484b-81cd-2f89f1558de1', _name: 'phil' }
2
New Round
{ _id: '3dab1d04-7263-41a6-ad1e-bfa9e201d377', _name: 'bob' }
2
New Round
{ _id: '9584fee5-3733-460d-a1bc-21c2ae47e78b', _name: 'luthor' }
2
New Round
{ _id: 'f676eea0-dfa2-44b5-8af7-28622b533eae', _name: 'jimmy' }
2
New Round
{ _id: 'd435a9dd-95e0-4a5f-b12f-781248fcefe4', _name: 'pauly' }
2
New Round
{ _id: '6b7d882c-7071-4cdf-8426-eb0ed25d2f02', _name: 'micky' }
3
6
undefined
Done loading!
以下是示例数据文件(sample.json)的内容:
[
{
"_id": "15fb781a-d2fc-4429-82c7-8eb3e0a007b7",
"_name": "bruce"
},
{
"_id": "02007ad3-2b25-46d9-a609-edacf9e151dc",
"_name": "ken"
},
{
"_id": "18913a7a-18e6-484b-81cd-2f89f1558de1",
"_name": "phil"
},
{
"_id": "3dab1d04-7263-41a6-ad1e-bfa9e201d377",
"_name": "bob"
},
{
"_id": "9584fee5-3733-460d-a1bc-21c2ae47e78b",
"_name": "luthor"
},
{
"_id": "f676eea0-dfa2-44b5-8af7-28622b533eae",
"_name": "jimmy"
},
{
"_id": "d435a9dd-95e0-4a5f-b12f-781248fcefe4",
"_name": "pauly"
},
{
"_id": "6b7d882c-7071-4cdf-8426-eb0ed25d2f02",
"_name": "micky"
}
]
答案 0 :(得分:3)
您正在创建一种竞争条件,当end
事件触发时,您的诺言将得以解决,该事件很可能会在所有插入操作完成之前发生。
由于您正在使用promise,因此您应该将insert操作包装在promise中,因为这是异步的。完成此操作后,您可以维护一系列可用于解决外部承诺的承诺。
请尝试以下操作:
const fs = require('fs');
const jstream = require('JSONStream');
// Simulated database insert
const insert = () => new Promise(res => setTimeout(res, 2000));
new Promise((res, rej) => {
let promises = [];
try {
const stream = fs.createReadStream('./sample.json');
console.log(1);
const p = stream.pipe(jstream.parse('*'))
p.on('data', (stuff) => {
console.log(2);
console.log("New Round");
console.log(stuff);
promises.push(insert());
});
p.on('end', () => {
console.log(3);
// v-- Resolve with a promise that waits for all
// inserts to finish
res(Promise.all(promises).then(a => a.length));
});
p.on('error', (err) => {
console.log(4);
rej(err);
})
} catch (err) {
console.log(5);
rej(err);
}
})
.then((count) => {
console.log(6);
console.log(count);
console.log("Done loading!");
})
.catch((err) => {
console.log(7);
console.log(err);
});