简体   繁体   English

async await或Promise不返回流事件

[英]async await or Promise not returning on stream event

I have the following function which returns a Promise where the function argument is an async function: 我有以下函数返回一个Promise,其中函数参数是一个异步函数:

  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 : 但是在从csv-parse创建的流中引发的可读事件期间调用createObjectFrom函数时:

  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 代码到达createObjectFromconsole.log语句

  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. 但是没有达到下面的console.dir声明,因为Promise似乎没有解决。

If I call createObjectFrom from a test outside of the stream processing then it resolves correctly. 如果我从流处理之外的测试中调用createObjectFrom ,那么它会正确解析。

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. 我有这个包含源代码和失败测试的repo。

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. 使用mocha测试promise时,需要从it函数返回promise。 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. return f ,现在一切都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM