npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sequenced

v1.0.0

Published

Chain async functions together without syntax noise

Downloads

5

Readme

sequenced

Abstraction over asynchronous operations in a series.

Why?

Even though today’s modern JavaScript provides a lot of tools to make writing asynchronous code easier, when you want to perform async operations in series, there’s still a lot of syntax noises.

Promises

const doThings = () => (Promise.resolve()
  .then(step1)
  .then(step2)
  .then(step3)
  .then(step4)
  .then(step5)
)

You see .then() everywhere!

Coroutines

const doThings = Promise.coroutine(function* () {
  const a = yield step1()
  const b = yield step2(a)
  const c = yield step3(b)
  const d = yield step4(c)
  return yield step5(d)
})

You see yield everywhere, and you have to make sure that every step function returns a Promise.

Async Functions

async function doThings () {
  const a = await step1()
  const b = await step2()
  const c = await step3()
  const d = await step4()
  return await step5()
}

You see await everywhere, and you have to keep track of which step can be await’ed and which can not.

sequenced

Using sequenced, it is reduced to:

const doThings = (sequenced
  (step1)
  (step2)
  (step3)
  (step4)
  (step5)
  .run
)

You can also use CoffeeScript with alternative syntax

doThings = sequenced [
  step1
  step2
  step3
  step4
  step5
]
.run

Motivation

A lot of testing frameworks (especially acceptance testing) come with its own way to handle asynchronity. For example, Nightwatch.js is very easy to use because the operations are chainable, and Nightwatch manage the operations queue by itself.

However, when creating more complex test suites, I find Nightwatch’s operation queue hard to understand (they don’t use promises). When I tried to do some advanced stuff, such as dropping the developer into an REPL, so that they can write test suites interactively (like REPL-driven development), the command doesn’t get run, because it’s waiting for the REPL to finish.

So I also looked at Webdriver.io, because they are Promise/A+ compliant, but to write a test suite, you need to switch between chaining and yielding (or .then()ing). The resulting test code is not as elegant as writing in Nightwatch. Moreover, you don’t get any automatic logging like in Nightwatch.

Most of what these test do is that they run asynchronous operation, one after the other. So why not abstract them?

It could look like this:

function test (browser) {
  return (sequenced
    (browser.init())
    (browser.url('https://example.com/'))
    (browser.setValue('.SearchField', 'cats'))
    (browser.click('.SearchButton'))
    (browser.getTitle())
    (assert.match(/meow/))
    .run()
  )
}

API

const sequenced = require('sequenced')

sequenced(action)... → SequencedAction

Starts a sequenced action.