106 lines
3.4 KiB
Plaintext
106 lines
3.4 KiB
Plaintext
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "BatchedFileReader", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return BatchedFileReader;
|
|
}
|
|
});
|
|
class BatchedFileReader {
|
|
constructor(reader){
|
|
this.reader = reader;
|
|
}
|
|
schedule(callback) {
|
|
if (!this.schedulePromise) {
|
|
this.schedulePromise = Promise.resolve();
|
|
}
|
|
this.schedulePromise.then(()=>{
|
|
process.nextTick(callback);
|
|
});
|
|
}
|
|
getOrCreateBatch() {
|
|
// If there is an existing batch and it's not completed, then reuse it.
|
|
if (this.batch && !this.batch.completed) {
|
|
return this.batch;
|
|
}
|
|
const batch = {
|
|
completed: false,
|
|
directories: [],
|
|
callbacks: []
|
|
};
|
|
this.batch = batch;
|
|
this.schedule(async ()=>{
|
|
batch.completed = true;
|
|
if (batch.directories.length === 0) return;
|
|
// Collect all the results for each of the directories. If any error
|
|
// occurs, send the results back to the loaders.
|
|
let values;
|
|
try {
|
|
values = await this.load(batch.directories);
|
|
} catch (err) {
|
|
// Reject all the callbacks.
|
|
for (const { reject } of batch.callbacks){
|
|
reject(err);
|
|
}
|
|
return;
|
|
}
|
|
// Loop over all the callbacks and send them their results.
|
|
for(let i = 0; i < batch.callbacks.length; i++){
|
|
const value = values[i];
|
|
if (value instanceof Error) {
|
|
batch.callbacks[i].reject(value);
|
|
} else {
|
|
batch.callbacks[i].resolve(value);
|
|
}
|
|
}
|
|
});
|
|
return batch;
|
|
}
|
|
async load(directories) {
|
|
// Make a unique array of directories. This is what lets us de-duplicate
|
|
// loads for the same directory.
|
|
const unique = [
|
|
...new Set(directories)
|
|
];
|
|
const results = await Promise.all(unique.map(async (directory)=>{
|
|
let files;
|
|
let error;
|
|
try {
|
|
files = await this.reader.read(directory);
|
|
} catch (err) {
|
|
if (err instanceof Error) error = err;
|
|
}
|
|
return {
|
|
directory,
|
|
files,
|
|
error
|
|
};
|
|
}));
|
|
return directories.map((directory)=>{
|
|
const found = results.find((result)=>result.directory === directory);
|
|
if (!found) return [];
|
|
if (found.files) return found.files;
|
|
if (found.error) return found.error;
|
|
return [];
|
|
});
|
|
}
|
|
async read(dir) {
|
|
// Get or create a new file reading batch.
|
|
const batch = this.getOrCreateBatch();
|
|
// Push this directory into the batch to resolve.
|
|
batch.directories.push(dir);
|
|
// Push the promise handles into the batch (under the same index) so it can
|
|
// be resolved later when it's scheduled.
|
|
const promise = new Promise((resolve, reject)=>{
|
|
batch.callbacks.push({
|
|
resolve,
|
|
reject
|
|
});
|
|
});
|
|
return promise;
|
|
}
|
|
}
|
|
|
|
//# sourceMappingURL=batched-file-reader.js.map |