Comparing version
@@ -25,1 +25,11 @@ export interface IDefer<T> { | ||
export declare function makeBroadcastStream<T>(): IBroadcastStream<T>; | ||
export interface ISingleStream<T> extends AsyncIterable<T> { | ||
next(value: T): void; | ||
throw(error: unknown): void; | ||
done(): void; | ||
} | ||
export declare function makeSingleStream<T>(): ISingleStream<T>; |
160
index.js
@@ -1,11 +0,14 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeBroadcastStream = void 0; | ||
'use strict' | ||
Object.defineProperty(exports, '__esModule', {value: true}) | ||
exports.default = makeDefer | ||
exports.makeBroadcastStream = makeBroadcastStream | ||
exports.makeSingleStream = makeSingleStream | ||
function makeDefer() { | ||
let resolve = undefined; | ||
let reject = undefined; | ||
let resolve = undefined | ||
let reject = undefined | ||
const promise = new Promise((rs, rj) => { | ||
resolve = rs; | ||
reject = rj; | ||
}); | ||
resolve = rs | ||
reject = rj | ||
}) | ||
return { | ||
@@ -15,9 +18,9 @@ resolve, | ||
promise | ||
}; | ||
} | ||
} | ||
exports.default = makeDefer; | ||
function makeBroadcastStream() { | ||
const listeners = []; | ||
let done = false; | ||
let defer = makeDefer(); | ||
const listeners = [] | ||
let done = false | ||
let defer = makeDefer() | ||
return { | ||
@@ -27,59 +30,124 @@ [Symbol.asyncIterator]() { | ||
async next() { | ||
const value = await defer.promise; | ||
defer = makeDefer(); | ||
return value; | ||
if (done) | ||
return {value: undefined, done: true} | ||
const value = await defer.promise | ||
defer = makeDefer() | ||
return value | ||
}, | ||
async return(value) { | ||
return { value: undefined, done: true }; | ||
return {value: undefined, done: true} | ||
}, | ||
async throw(e) { | ||
return { value: undefined, done: true }; | ||
return {value: undefined, done: true} | ||
} | ||
}; | ||
} | ||
}, | ||
listen(onNext, { onError, onDone } = {}) { | ||
if (done) | ||
throw new Error('Cannot listen after done'); | ||
const listener = { onNext, onError, onDone }; | ||
listeners.push(listener); | ||
listen(onNext, {onError, onDone} = {}) { | ||
if (done) { | ||
onDone?.() | ||
return () => { | ||
} | ||
} | ||
const listener = {onNext, onError, onDone} | ||
listeners.push(listener) | ||
return function removeListener() { | ||
const idx = listeners.lastIndexOf(listener); | ||
const idx = listeners.lastIndexOf(listener) | ||
if (idx >= 0) | ||
listeners.splice(idx, 1); | ||
}; | ||
listeners.splice(idx, 1) | ||
} | ||
}, | ||
next(value) { | ||
if (done) | ||
throw new Error('Cannot next after done'); | ||
defer.resolve({ value, done: false }); | ||
for (const { onNext } of listeners) | ||
return | ||
defer.resolve({value, done: false}) | ||
for (const {onNext} of listeners) | ||
try { | ||
onNext(value); | ||
onNext(value) | ||
} catch { | ||
} | ||
catch { } | ||
}, | ||
throw(error) { | ||
if (done) | ||
throw new Error('Cannot throw after done'); | ||
done = true; | ||
defer.reject(error); | ||
for (const { onError } of listeners) | ||
return | ||
done = true | ||
defer.reject(error) | ||
for (const {onError} of listeners) | ||
try { | ||
onError?.(error); | ||
onError?.(error) | ||
} catch { | ||
} | ||
catch { } | ||
}, | ||
done() { | ||
if (done) | ||
throw new Error('Cannot done after done'); | ||
done = true; | ||
defer.resolve({ value: undefined, done: true }); | ||
for (const { onDone } of listeners) | ||
return | ||
done = true | ||
defer.resolve({value: undefined, done: true}) | ||
for (const {onDone} of listeners) | ||
try { | ||
onDone?.(); | ||
onDone?.() | ||
} catch { | ||
} | ||
catch { } | ||
}, | ||
}; | ||
} | ||
} | ||
exports.makeBroadcastStream = makeBroadcastStream; | ||
function makeSingleStream() { | ||
// at least one of chunk or defers is empty, all the time | ||
const chunk = [] | ||
const defers = [] | ||
let done = false | ||
let error | ||
return { | ||
[Symbol.asyncIterator]() { | ||
return { | ||
async next() { | ||
if (chunk.length) | ||
return chunk.shift() | ||
if (done) { | ||
if (error) | ||
throw error | ||
return {value: undefined, done: true} | ||
} | ||
// chunk must currently be empty, it is safe to make defers non-empty | ||
const defer = makeDefer() | ||
defers.push(defer) | ||
return defer.promise | ||
}, | ||
async return(value) { | ||
return {value: undefined, done: true} | ||
}, | ||
async throw(e) { | ||
return {value: undefined, done: true} | ||
} | ||
} | ||
}, | ||
next(value) { | ||
if (done) | ||
return | ||
if (defers.length) { | ||
const defer = defers.shift() | ||
defer.resolve({value, done: false}) | ||
return | ||
} | ||
// defers must currently be empty, it is safe to make chunk non-empty | ||
chunk.push({value, done: false}) | ||
}, | ||
throw(err) { | ||
if (done) | ||
return | ||
done = true | ||
error = err | ||
for (const defer of defers) | ||
defer.reject(err) | ||
defers.length = 0 | ||
}, | ||
done() { | ||
if (done) | ||
return | ||
done = true | ||
for (const defer of defers) | ||
defer.resolve({value: undefined, done: true}) | ||
defers.length = 0 | ||
}, | ||
} | ||
} |
{ | ||
"name": "jdefer", | ||
"version": "0.0.14", | ||
"version": "0.1.0", | ||
"main": "index.js", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/tranvansang/jdefer", |
@@ -13,2 +13,4 @@ # Javascript promise defer library | ||
In 2024: recommended using [`Promise.withResolvers()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers). | ||
```typescript | ||
@@ -15,0 +17,0 @@ import makeDefer from 'jdefer' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
8727
50.39%313
76.84%68
3.03%0
-100%