I have the following function which returns a Promise where the function argument is an async function:
createObjectFrom(record) {
const self = this;
return new Promise(async (resolve, reject) => {
let obj = {};
for(let i = 0, l = self.opts.transformers.length; i < l; i++) {
let transformer = self.opts.transformers[i];
const headerIndex = findIndex(self.headers, (header) => {
return header === transformer.column;
});
let csvValue = record[headerIndex];
const lookUp = transformer.options.lookUp;
const whereClause = {};
whereClause[lookUp.column] = csvValue;
console.log('before await');
const result = await self.knex(lookUp.table).where(whereClause).select(lookUp.scalar);
console.dir(result);
obj[transformer.field] = result[0][lookUp.scalar];
}
return resolve(obj);
});
}
If I call the function like this from at test, it all executes correctly:
it('creates the transformed object', async () => {
const csvRecord = ['PREMIER', '07/11/1998', manager, 'Liverpool', 'Wimbledon', 0, 1, 'A', 0, 1, 'A'];
const record = await transformer.createObjectFrom(csvRecord);
expect(record.division).to.equal('PREMIER');
}
But when calling the createObjectFrom
function during a readable event which is raised from a stream created from csv-parse:
onReadable() {
let record = this.parser.read();
if (record === null) {
return;
}
if (this.parser.count <= 1) {
this.headers = record;
} else {
const recordPromises = this.createObjectFrom(record);
this.recordPromises.push( newRecord );
}
}
THe code gets to the console.log
statement below in createObjectFrom
console.log('before here');
const result = await self.knex(lookUp.table).where(whereClause).select(lookUp.scalar);
console.dir(result);
But does not get to the console.dir
statement below as the Promise does not seem to resolve.
If I call createObjectFrom
from a test outside of the stream processing then it resolves correctly.
I have also tried refactoring async await out of this to just return a promise but it is still broke.
If I console.dir the promises on the [end][3] event of the stream they look like this:
[ Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined },
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined } ]
I have this repo which has the source code and a failing test.
I am baffled as to what is going on.
The following test also passes so it is definitely something to do with the stream:
it('creates the transformed object', async () => {
const csvRecords = [
['PREMIER', '07/11/1998', manager, 'Liverpool', 'Wimbledon', 0, 1, 'A', 0, 1, 'A'],
['PREMIER', '11/11/1998', manager, 'QPR', 'Sunderland',3,3, 'Sunderland',0,0,'Sunderland'],
['PREMIER', '14/11/1998', manager, 'Southampton', 'Liverpool', 3, 3, 'D', 0, 0, 'D']
];
for(var i = 0, l = csvRecords.length; i < l; i++) {
const csvRecord = csvRecords[i];
const record = await transformer.createObjectFrom(csvRecord);
expect(record.division).to.equal('PREMIER');
expect(record.manager_id).to.equal(manager_id);
}
}
why you don't change your code like this:
createObjectFrom: async (record) => {
const self = this;
// return new Promise(async (resolve, reject) => {
let obj = {};
for(let i = 0, l = self.opts.transformers.length; i < l; i++) {
let transformer = self.opts.transformers[i];
const headerIndex = findIndex(self.headers, (header) => {
return header === transformer.column;
});
let csvValue = record[headerIndex];
const lookUp = transformer.options.lookUp;
const whereClause = {};
whereClause[lookUp.column] = csvValue;
console.log('before await');
const result = await self.knex(lookUp.table).where(whereClause).select(lookUp.scalar);
console.dir(result);
obj[transformer.field] = result[0][lookUp.scalar];
}
return obj;
// return resolve(obj);
// });
}
OMG, what an arse, it was because I was not returning the promise from the test. When testing promises with mocha, you need to return the promise from the it
function. If you do this it all works. What a fool!
So if I change the test to this:
describe('transformer', () => {
it('transforms the data and imports the csv file', () => {
const ignoreIf = (data) => data[3] !== 'Liverpool' && data[4] !== 'Liverpool';
const opts = { table: 'results', file: __dirname + '/fixtures/test.csv', encoding: 'utf8', transformers, ignoreIf: ignoreIf };
const f = seeder(opts)(knex, Promise);
return f.then((results) => {
console.dir(results);
});
});
I return f
and all is good now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With