rdfjs / N3.js

Lightning fast, spec-compatible, streaming RDF for JavaScript
http://rdf.js.org/N3.js/
Other
676 stars 127 forks source link

How to wait for parsing to be done? #378

Closed flyon closed 3 months ago

flyon commented 3 months ago

This might be a silly question but I don't see it mentioned and I'm actually not sure how to do it.

const quads = new Set();
const parser = new N3.Parser();
//this file contains hundrets of quads
const rdfStream = fs.createReadStream(filePathN3);
parser.parse(rdfStream, (quad) => {
    quads.add(quad);
});
rdfStream.on('close', function () {
   //logs 1
  console.log(quads.size);
});
//logs 0 
console.log(quads.size);

On the last line of this code the set of quads is 0 because parsing is async. listening for the readstream to close also doesnt work as it logs 1? I want to create a promise somehow that I can await and it resolves when parsing is done. I can handle the promise part, but how to know when the parsing is done?

jeswr commented 3 months ago

If you don't care about performance then doing this syncronously is fine e.g. you can do https://github.com/jeswr/shacl-test-as-object/blob/80398f9abbb95867e08eb25f1c51083aabbc3d65/lib/index.ts#L30-L32

If you want to do things in a streaming manner then the following works.

import * as fs from 'fs';
import * as N3 from 'n3';

function parseToStore(filePath: string) {
    const parser = new N3.StreamParser(),
        store = new N3.Store(),
        rdfStream = fs.createReadStream(filePath);
    return new Promise((resolve, reject) => {
       store.import(parser.import(rdfStream))
                .on('error', reject)
                .on('end', () => resolve(store))
    });
}

parseToStore('cartoons.ttl').then(console.log)

Note that you'll want to be adding your quads to a N3.Store rather than a Set as well because you can have multiple quads that contain the same information but are different JS objects (see https://github.com/iherman/rdfjs-c14n/issues/10).

flyon commented 3 months ago

perfect this works thanks. Using the stream parser + import and then using 'end' is what I was looking for.