getify / CAF

Cancelable Async Flows (CAF)
MIT License
1.34k stars 46 forks source link

ReferenceError: AbortController is not defined #23

Closed NorinMp143 closed 3 years ago

NorinMp143 commented 3 years ago

file:///home/ubuntu/dwhelper/Digging%20into%20Nodejs/Learning%20Digging%20into%20Nodejs/node_modules/caf/dist/esm/shared.mjs:5 const CLEANUP_FN=Symbol("Cleanup Function"),TIMEOUT_TOKEN=Symbol("Timeout Token");class cancelToken{constructor(n=new AbortController){var s;this.controller=n,this.signal=n.signal;var handleReject=(n,i)=>{var doRej=()=>{if(i){var n=this.signal&&this.signal.reason?this.signal.reason:void 0;i(n),i=null}};this.signal.addEventListener("abort",doRej,!1),s=()=>{this.signal&&(this.signal.removeEventListener("abort",doRej,!1),this.signal.pr&&(this.signal.pr[CLEANUP_FN]=null)),doRej=null}};this.signal.pr=new Promise(handleReject),this.signal.pr[CLEANUP_FN]=s,this.signal.pr.catch(s),handleReject=s=null}abort(n){this.signal&&!("reason"in this.signal)&&(this.signal.reason=n),this.controller&&this.controller.abort()}discard(){this.signal&&(this.signal.pr&&(this.signal.pr[CLEANUP_FN]&&this.signal.pr[CLEANUP_FN](),this.signal.pr=null),this.signal=this.signal.reason=null),this.controller=null}}export default{CLEANUP_FN:CLEANUP_FN,TIMEOUT_TOKEN:TIMEOUT_TOKEN,cancelToken:cancelToken,signalPromise:signalPromise,processTokenOrSignal:processTokenOrSignal};export{CLEANUP_FN};export{TIMEOUT_TOKEN};export{cancelToken};export{signalPromise};export{processTokenOrSignal};function signalPromise(n){if(n.pr)return n.pr;var s,i=new Promise((function c(i,r){s=()=>r(),n.addEventListener("abort",s,!1)}));return i[CLEANUP_FN]=function cleanup(){n&&(n.removeEventListener("abort",s,!1),n=null),i&&(i=i[CLEANUP_FN]=s=null)},i.catch(i[CLEANUP_FN]),i}function processTokenOrSignal(n){n instanceof AbortController&&(n=new cancelToken(n));var s=n&&n instanceof cancelToken?n.signal:n;return{tokenOrSignal:n,signal:s,signalPr:signalPromise(s)}} ^

ReferenceError: AbortController is not defined at new cancelToken (file:///home/ubuntu/dwhelper/Digging%20into%20Nodejs/Learning%20Digging%20into%20Nodejs/node_modules/caf/dist/esm/shared.mjs:5:119) at Function.timeout (file:///home/ubuntu/dwhelper/Digging%20into%20Nodejs/Learning%20Digging%20into%20Nodejs/node_modules/caf/dist/esm/caf.mjs:5:1158) at file:///home/ubuntu/dwhelper/Digging%20into%20Nodejs/Learning%20Digging%20into%20Nodejs/cli3.js:43:28 at ModuleJob.run (internal/modules/esm/module_job.js:152:23) at async Loader.import (internal/modules/esm/loader.js:166:24) at async Object.loadESM (internal/process/esm_loader.js:68:5)

code ->

!/usr/bin/env node

"use strict";

import util from 'util'; import path from 'path'; import fs from 'fs'; import zlib from 'zlib';

import minimist from 'minimist'; import { Transform } from 'stream'; import { CAF } from 'caf';

const __dirname = path.resolve();

var args = minimist(process.argv.slice(2),{ boolean: ['help', 'in', 'out', 'compress', 'uncompress'], string: ['file'] });

processFile = CAF(processFile);

function streamComplete(stream){ return new Promise (function c(res){ stream.on("end",res); }) }

var BASH_PATH = path.resolve( process.env.BASE_PATH || __dirname)

var OUTFILE = path.join(BASH_PATH, 'out.txt');

if(args.help){ printHelp(); } else if(args.in || args._.includes('-')){ const timeoutToken = CAF.timeout(3, "Timeout!"); processFile(timeoutToken,process.stdin) .catch(error); } else if(args.file){ const stream = fs.createReadStream(path.join(BASH_PATH,args.file)); const timeoutToken = CAF.timeout(3, "Timeout!"); processFile(timeoutToken,stream) .then((data)=>{ console.log('Complete!'); }) .catch(error); } else{ error('Incorrect usage',true) }

// **

function *processFile (signal,inStream){ let outStream = inStream;

if(args.uncompress){ const gunzipStream = zlib.createGunzip(); outStream = outStream.pipe(gunzipStream); }

const upperStream = new Transform({ transform(chunk, enc, cb){ this.push(chunk.toString().toUpperCase()); cb(); } }); outStream = outStream.pipe(upperStream); if(args.compress){ const gzipStream = zlib.createGzip(); outStream = outStream.pipe(gzipStream); OUTFILE = ${OUTFILE}.gz; } let targetStream; if(args.out){ targetStream = process.stdout; } else{ targetStream = fs.createWriteStream(OUTFILE); } outStream.pipe(targetStream); signal.pr.catch(function f(){ outStream.unpipe(targetStream); outStream.destroy(); }) yield streamComplete(outStream) }

function error(msg, includeHelp= false){ console.log(msg); if(includeHelp){ console.log(''); printHelp(); } }

function printHelp(){ console.log("cli3 usage:"); console.log(" cli3.js --file={FILENAME}"); console.log(""); console.log(" --help print this help"); console.log(" --file process the file"); console.log(" --in, - process stdin"); console.log(" --out print the output"); console.log(" --compress gzip the output"); console.log(" --uncompress un-zip the input"); console.log(""); }

getify commented 3 years ago

What version of Node are you running?

NorinMp143 commented 3 years ago

v14.16.1

getify commented 3 years ago

Node 14.x and below need the polyfill which is included in the various dist directories alongside the CAF file(s). With non-ESM CAF, the polyfill is loaded automatically. But if you do import like you're showing there, you'll need to first manually require(..) the polyfill. In Node 16+, the polyfill is no longer needed as AbortController is a built-in.

NorinMp143 commented 3 years ago

thank you for the explanation. now I am trying with require(...) but I got the error after then I try different versions of CAF and I got that CAF@9.1.0 and below are compatible with Node 14.x and below versions. But you said that in non-ESM CAF, the polyfill loaded automatically but not working in the latest version CAF@12.0.1 now I am using CAF@9.1.0 which is working perfectly. Is there any way that if I use require(...) and latest version of CAF with Node 14.x

getify commented 3 years ago

If the polyfill is not loading automatically, can you try loading it (with require)? Does that not work?

getify commented 3 years ago

I just tried this and it seems to work fine:

$ node --version
v14.15.5

$ cat test-caf.mjs
import { createRequire } from "module";
const require = createRequire(import.meta.url);

require("./node_modules/caf/dist/abortcontroller-polyfill-only.js");

import { CAF as c1 } from "caf";
import c2 from "caf/caf";

console.log( new c1.cancelToken() );
console.log( new c2.cancelToken() );

$ node test-caf.mjs
cancelToken {
  controller: AbortController {},
  signal: AbortSignal {
    pr: Promise { <pending>, [Symbol(Cleanup Function)]: [Function: s] }
  }
}
cancelToken {
  controller: AbortController {},
  signal: AbortSignal {
    pr: Promise { <pending>, [Symbol(Cleanup Function)]: [Function: s] }
  }
}
getify commented 3 years ago

ESM builds (even in Node) are not intended to automatically load a polyfill, as this sort of breaks the assumptions of module systems.

However, I agree there was a regression for non-ESM usage in Node 14 and below, where it used to load the polyfill automatically and it stopped doing so. Sorry about that -- I'm fixing it.

getify commented 3 years ago

I've released CAF v13.0.0 which should fix the Node 14 regression with non-ESM format and the polyfill. For ESM format, you'll need to manually include the polyfill for Node 14 and below. Starting with Node 16, the polyfill is no longer required.