用于大文件异步迭代的生成器
问题描述:
假设我有一个名为openShapeFile
的函数,它读取一个文件并生成一个Promise,它包装具有read
函数的源对象,该函数返回一个Promise,将Shapefile中的实际值,并且有一个.done
布尔值,可用于判断是否已到达文件末尾。用于大文件异步迭代的生成器
实际上,shapefile.open
从这里:
如果我现在想读文件到一个数据库中,我可以说:
openShapeFile(`shapefile.shp`).then((source) => source.read()
.then(function log(result) {
if (result.done) {
return
} else {
let query = `INSERT INTO geodata(geometry, id, featcode) VALUES(ST_GeomFromGeoJSON('${
JSON.stringify(Object.assign({}, result.value.geometry, {coordinates: result.value.geometry.coordinates.map(JSON.stringify)}))
}'), '${
result.value.properties.ID
}', ${
result.value.properties.FEATCODE
});`
query = query.split('"[[').join('[[').split(']]"').join(']]')
return pool.query(query).then((result) => {
return source.read().then(log)
})
}
})).then(() => console.log(dirCount)).catch(err => 'Problem here')))
这只是工作,但有一个递归承诺(奇怪)
所以作为一个练习和/或看看它是否会产生更多的清晰度,我决定把它改写成发电机,产生如下的东西:
function *insertQuery(query) {
const result = pool.query(query)
return result
}
const shapeFileGenerator = co.wrap(function* (source) {
while (true) {
const result = yield source.read()
if (result.done) {
return yield {}
} else {
let query = `INSERT INTO geodata(geometry, id, featcode) VALUES(ST_GeomFromGeoJSON('${
JSON.stringify(Object.assign({}, result.value.geometry, {coordinates: result.value.geometry.coordinates.map(JSON.stringify)}))
}'), '${
result.value.properties.ID
}', ${
result.value.properties.FEATCODE
});`
query = query.split('"[[').join('[[').split(']]"').join(']]')
yield* insertQuery(query)
}
}
})
openShapeFile(`shapefile.shp`).then((source) => {
const s = shapeFileGenerator(source)
})))
现在这个工程!它读取所有的数据! 但是,我有点讨厌无限循环,并且我从不直接调用.next。我该如何重做?用发电机做这种事的惯用方法是什么?看来我应该能写一个合适的发电机与s.next()
导致source.read()
?
答
我会写
async function readFileToDB(filename) {
const source = await openShapeFile(filename);
for (let {value, done} = await source.read(); !done; {value, done} = await source.read()) {
const query = `INSERT INTO geodata(geometry, id, featcode) VALUES(ST_GeomFromGeoJSON('${
JSON.stringify(value.geometry)
}'), '${
value.properties.ID
}', ${
value.properties.FEATCODE
});`
const result = await pool.query(query);
}
console.log(dirCount);
}
readFileToDB(`shapefile.shp`).catch(err => console.error('Problem here', err));
强硬。我不认为有什么不对递归的解决办法。
好像我应该能够编写与
s.next()
适当发生器产生一个source.read()
?
不,发电机是同步的。不过,您可能需要查看async iteration proposal。
不要使用带有承诺的发电机!使用'async' /'await'! – Bergi
“*我从来没有直接调用.next。*” - co库为你做。你为什么想要这样做? – Bergi