You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

async-caf

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

async-caf - npm Package Compare versions

Comparing version

to
3.0.4

2

dist/caf.js
/*! caf.js
v3.0.3 (c) 2018 Kyle Simpson
v3.0.4 (c) 2018 Kyle Simpson
MIT License: http://getify.mit-license.org

@@ -4,0 +4,0 @@ */

{
"name": "async-caf",
"version": "3.0.3",
"version": "3.0.4",
"description": "Wrapper for generators as cancelable async functions",

@@ -5,0 +5,0 @@ "main": "./dist/caf.js",

@@ -230,2 +230,53 @@ # Cancelable Async Functions (CAF)

### Beware Of Token Reuse
Beware of creating a single cancelation token that is reused for separate chains of function calls. Unexpected results are likely, and they can be extremely difficult to debug.
As illustrated earlier, it's totally OK and intended that a single cancelation token `signal` be shared across all the functions in **one** chain of calls (`A` -> `B` -> `C`). But reusing the same token **across two or more chains of calls** (`A` -> `B` -> `C` and `D` -> `E` -> `F`) is asking for trouble.
Imagine a scenario where you make two separate `fetch(..)` calls, one after the other, and the second one runs too long so you cancel it via a timeout:
```js
var one = CAF( function *one(signal){
signal.pr.catch( reason => {
console.log( `one: ${reason}` );
} );
return yield fetch( "http://some.tld/", {signal} );
} );
var two = CAF( function *two(signal,v){
signal.pr.catch( reason => {
console.log( `two: ${reason}` );
} );
return yield fetch( `http://other.tld/?v=${v}`, {signal} );
} );
var token = CAF.cancelToken();
one( token.signal )
.then( function(v){
// only wait 3 seconds for this request
setTimeout( function(){
token.abort( "Second response too slow." );
}, 3000 );
return two( token.signal, v );
} )
.then( console.log, console.error );
// one: Second response too slow. <-- Oops!
// two: Second response too slow.
// Second response too slow.
```
When you call `token.abort(..)` to cancel the second `fetch(..)` call in `two(..)`, the `signal.pr.catch(..)` handler in `one(..)` still gets called, even though `one(..)` is already finished. That's why `"one: Second response too slow."` prints unexpectedly.
The underlying gotcha is that a cancelation token's `signal` has a single `pr` promise associated with it, and there's no way to reset a promise or "unregister" `then(..)` / `catch(..)` handlers attached to it once you don't need them anymore. So if you reuse the token, you're reusing the `pr` promise, and all registered promise handlers will be fired, even old ones you likely don't intend.
The above snippet illustrates this problem with `signal.pr.catch(..)`, but any of the other ways of listening to a promise -- such as `yield` / `await`, `Promise.all(..)` / `Promise.race(..)`, etc -- are all susceptible to the unexpected behavior.
The safe and proper approach is to always create a new cancelation token for each chain of **CAF**-wrapped function calls. For good measure, always unset any references to a token once it's no longer needed; thus, you won't accidentally reuse it, and the JS engine can properly garbage collect it.
## npm Package

@@ -232,0 +283,0 @@