Got: Async iterator does not work on Node.js 14

Created on 22 Apr 2020  路  6Comments  路  Source: sindresorhus/got

Describe the bug

  • Node.js version: 14.0.0
  • OS & version: Ubuntu 19
  • Got version: 11.0.2

With the brand new node 14 and when awaiting something before consuming a got stream with the async iterator, I don't get any chunks. I don't know if this bug is node related but in my tries, I was able to successfully request as this way with the native http module or in all cases under node 13, as this bug only occurs with node 14. It may be related to #1159.

Code to reproduce

Server part
'use strict';
const http = require('http');
const server = http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    setTimeout(() => res.write('chunk 1'), 500);
    setTimeout(() => res.write('chunk 2'), 1000);
    setTimeout(() => res.write('chunk 3'), 1500);
    setTimeout(() => res.end(), 2000);
});
server.listen(8000);
Got client part
'use strict';
const got = require('got');
(async () => {
    try {
        const req = await got.stream('http://localhost:8000');
        req.on('end', () => {
            console.log('end event');
        });

        await new Promise((resolve) => {
            setTimeout(resolve, 100);
        })

        for await (const data of req) {
            console.log('data', data.toString())
        }
        console.log(`after for await`);
    } catch (e) {
        console.log(`error: error=${e}`);
    }
})();
Native node client part
'use strict';
const http = require('http');
const {once} = require('events');
(async () => {
    try {
        const req = http.request('http://localhost:8000');
        req.end();

        const [res] = await once(req, 'response');
        res.on('end', () => {
            console.log('end event');
        });

        await new Promise((resolve) => {
            setTimeout(resolve, 100);
        })

        for await (const data of res) {
            console.log('data', data.toString())
        }
        console.log(`after for await`);
    } catch (e) {
        console.log(`error: error=${e}`);
    }
})();

Expected behavior

data chunk 1
data chunk 2
data chunk 3
end event
after for await

Actual behavior

Only for got client + node 14:

after for await

For other combinations, (native client + node 13/14 or got client + node 13), the actual behavior is the expected behavior

Checklist

  • [x] I have read the documentation.
  • [x] I have tried my code with the latest version of Node.js and Got.
bug external

All 6 comments

I have traced down a maybe similar issue on this library when using node v14.

In this case is making webdriverio fail since a request from got never succeeds nor it raises an error.

The code flows through as-promise.js and ends up returning with _a.aborted = true, which leave the application in a nondeterministic state.

   if ((_a = response.req) === null || _a === void 0 ? void 0 : _a.aborted) {
                // Canceled while downloading - will throw a `CancelError` or `TimeoutError` error
                return;
            }

In case someone want to take a look, but this is the a contrived repro case:
https://github.com/diervo/wdio-repro-example

For the record: https://github.com/webdriverio/webdriverio/issues/5319

Haven't looked at this yet, will do later today.

Very nice catch @szmarczak, thanks for digging deep in node internals !

We need to wait for a 14.2.0 release.

Node.js 14.2.0 got released 20h ago, I can confirm that it's fixed now.

Node.js 14.2.0 got released 20h ago, I can confirm that it's fixed now.

I can confirm too

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lukehorvat picture lukehorvat  路  3Comments

dAnjou picture dAnjou  路  3Comments

erfanium picture erfanium  路  3Comments

tkoelpin picture tkoelpin  路  3Comments

alvis picture alvis  路  3Comments