+10
-0
@@ -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>; |
+10
-0
@@ -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>; |
+114
-46
@@ -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 | ||
| }, | ||
| } | ||
| } |
+108
-41
| export default 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 { | ||
@@ -12,8 +12,9 @@ resolve, | ||
| promise | ||
| }; | ||
| } | ||
| } | ||
| export function makeBroadcastStream() { | ||
| const listeners = []; | ||
| let done = false; | ||
| let defer = makeDefer(); | ||
| const listeners = [] | ||
| let done = false | ||
| let defer = makeDefer() | ||
| return { | ||
@@ -23,58 +24,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 { } | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
| export 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 | ||
| }, | ||
| } | ||
| } |
+1
-1
| { | ||
| "name": "jdefer", | ||
| "version": "0.0.14", | ||
| "version": "0.1.0", | ||
| "main": "index.js", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/tranvansang/jdefer", |
+2
-0
@@ -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' |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
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%