
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
Define business logic in cancellable, forkable, asynchronous javascript generator definitions and promises
A tool that allows you to define logic with the power of iterables, promises and observables alike using the syntax of javascript generators
It solves the following common issues:
function* main() {
// this call returns a promise, the job will wait for it to finish
const user = yield getUser();
while (true) {
const data = yield fetchData();
yield delay(1000);
}
}
const job = immediate(main());
In this example two things stand out:
while(true): Wouldn't this cause an infinite loop that can't be stopped? not necessarily, you can always cancel job, preventing them from going forever, this is
something that you can't do using async/await.delay(1000): This is an effect, the API provides a list of effects you can use to control the flow of the application, this one will block the job for 1000 ms.latest(generatorFn): FunctionCreates a job factory that will trigger the generator function every time its called and return a promise that resolves to the return value of the job.
Its important to note latest only allows for one thread to run, and will cancel any ongoing executions every time its called again.
Example:
// any subsequent call made to handle click will cancel the execution and start a new one
const handleClick = latest(function* (event) {
yield delay(1000);
alert('clicked');
})
// if a user clicks the button several times under a second only the latest one will register
document.addEventListener(btn, 'click', handleClick)
channel(generatorFn): FunctionCreates a job factory that will place the job at the end of the execution queue and will trigger once all previous calls are finished.
Its important to note latest only allows for one thread to run and all queued jobs will be blocked.
yield <expression>: Iterable|Promise|ArrayWithin jobs you can yield many kinds of expressions, depending on the type of the expression the job will handle it differently:
yield fork(input: Iterable|Promise|Array): JobCreates a new non-blocking job from the given input and appends it to the job that spawns it. Useful when you need to keep track of child job execution.
yield race(...inputs: Iterable|Promise|Array): PromiseCreates a job for each different input and races them, the first one to finish will return and cancels the rest.
yield delay(ms: number, [val]): PromiseA promise that resolves after the given ms, if val is specified, it will resolve to that value.
yield latest(observable: observable, listener: (value) => Iterable|Promise|Array): JobSame as yield observable but if the observable emits a value before the latest job started
by the previous value is still running, it will cancel it and start again with the new value.
yield cancel(job: Job)Cancels the given job, same as job.cancel().
yield forever()Stops the job forever.
yield teardown(input: Iterable|Promise|Array, handler: Function): PromiseAllows you to define custom cancellation logic for your blocking calls. When your job is cancelled the cancellation propagates to all of its children but this doesn't prevent external logic from cancelling as well. This effect allows you to "subscribe" to the cancellation event and fire up the handler when it happens, this is useful to tell external logic that the job is no longer paying attention to its result and that it may stop what its doing.
Example:
// `request` adds an `.abort` method to its returned promise
function* upload() {
const result = yield teardown(
// this value is "thenable" and blocks the job
request(url, file),
// will called if this job is cancelled at any time
req => req.abort()
)
// if the job is cancelled at this point the `.abort` method
// wont be called
return result
}
class JobJob#promise: Promise: a promise that resolves when the job (and all its children) finishes
succesfully (no errors emitted), it will resolve if the job is cancelled, but with no result
value.Job#cancel(): cancels the job (and all of its children).Job#spawn(input): creates a child job from the inputJob#free(): cancel all the childrenJob#running: Boolean: is the job still running.Job#cancelled: Boolean: was the job cancelled.Job#resolved: Boolean: was the job resolved.Job#rejected: Boolean: was the job rejected.effect(payloadCreator, handler): (...args) => effectAllows you to define your own effects
payloadCreator: (...args): A function that will transform ...args passed to the effect into a
single payload, you should define your effect's function signature using this function.handler: (job: Job, payload: any): The handler function will be invoked when the effect is
yielded by a job, the job is the one yielding the effect and the payload is the
result of calling payloadCreator with the arguments passed to the effect when yielded. The handler
can return a promise as well.Example:
const race = effect(
// payloadCreator: concats all parameters into an array
(...inputs) => inputs,
// handler: invoked with the result of the payloadCreator
(job, inputs) => {
const children = inputs
.map(item => new Job(item))
return Promise.race(children.map(child => child.promise))
.then(result => {
children.forEach(child => child.cancel())
return result
})
}
)
Jobs can have children, these will affect how your job behaves. They can be created by effects such as fork, race or latest.
The following rules apply:
Jobs can throw errors as well as handle them, for most use cases the handling of errors should be exactly like async/await functions do. However if a child job throws an error to its parent there's no try/catch to stop it, make sure to catch errors within the job, otherwise they would just propagate indefinetly.
Wait for an amount of job to complete
function* main() {
try {
// resolves when the 3 are done
const [user, news, notifications] = yield [
getUser(),
getNewsfeed(),
getNotifications()
]
} catch (err) {
// if any of the 3 above emit an error will be handled here
}
}
function* pollNewsfeed() {
while (true) {
const news = yield getNewsfeed()
// ...
yield delay(1000)
}
}
function* main() {
// start non-blocking job
const job = yield fork(pollNewsfeed())
yield delay(8000)
// cancel the job after 8 seconds
yield cancel(job)
}
FAQs
Define business logic in cancellable, forkable, asynchronous javascript generator definitions and promises
The npm package leslie receives a total of 1 weekly downloads. As such, leslie popularity was classified as not popular.
We found that leslie demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.