2017-06-13 48 views
0

假设我有一个名为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()

+0

不要使用带有承诺的发电机!使用'async' /'await'! – Bergi

+0

“*我从来没有直接调用.next。*” - co库为你做。你为什么想要这样做? – Bergi

回答

-1

你可以编写你的逻辑,就好像它是同步的,并通过顺序执行器nsynjs执行。下面是稍加修改的工作例如在this file测试:

main.js:如果某些函数调用返回承诺

Nsynjs会自动检测。如果是的话,它会等待承诺解决,把它的结果放到data属性中,然后才继续下一个表达式。

0

我会写

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