【发布时间】:2017-11-15 03:14:44
【问题描述】:
假设我有一个名为 openShapeFile 的函数,它读取一个文件,并生成一个包装源对象的 Promise,该对象具有一个 read 函数,它返回一个包装 Shapefile 中的实际值的 Promise,并具有.done 布尔值,可用于判断是否已到达文件末尾。
实际上,shapefile.open 来自这里:
https://www.npmjs.com/package/shapefile
如果我现在想将文件读入数据库,我可以说:
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()?
【问题讨论】:
-
不要使用带有 Promise 的生成器!使用
async/await! -
"我从不直接调用 .next。" -
co库会为您做到这一点。你为什么要这样做?
标签: javascript asynchronous generator postgis idioms