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

ember-concurrency-async

v1.0.0

Published

Async task functions for ember-concurrency

Downloads

8,934

Readme

ember-concurrency-async

This addon introduces an alternative syntax for ember-concurrency tasks that uses async methods instead of generator methods:

import Component from '@glimmer/component';
import { task } from 'ember-concurrency';

class FooComponent extends Component {
  @task async myTask(foo, bar) {
    let resolvedFoo = await foo;
    let resolvedBar = await this.process(bar);
    return resolvedFoo + resolvedBar;
  }

  async process(bar) {
    // ...
  }
}

The main advantage of the async method syntax over the generator method syntax is that it works better with the TypeScript compiler and things powered by it, such as the JavaScript language server in Visual Studio Code.

Due to limitations in TypeScript's understanding of generator functions, it is not possible to express the realtionship between the left and right hand side of a yield expression. In the case of ember-concurrency task functions, we would like to inform the compiler that yielding a value "returns" its resolved value. If yield is a function, this is how we would type it:

type Resolved<T> = T extends PromiseLike<infer R> ? R : T;

function yield<T>(yieldable: T): Resolved<T>;

Unfortunately, this is not possible in TypeScript today. However, the await keyword in async functions have exactly the semantics we want, and TypeScript already understands that natively. This addon allows you to take advantage of that by authoring tasks in the async methods syntax, but transforms the async methods into the generator methods expected by ember-concurrency's runtime code using a babel plugin.

The example from earlier will be transformed into this:

import Component from '@glimmer/component';
import { task } from 'ember-concurrency';

export default class FooComponent extends Component {
  @task *myTask(foo, bar) {
    let resolvedFoo = yield foo;
    let resolvedBar = yield this.process(bar);
    return resolvedFoo + resolvedBar;
  }

  async process(bar) {
    // ...
  }
}

Note that only the async method annotated by the @task decorator was rewritten into a generator method.

Compatibility

  • Ember.js v3.12 or above
  • Ember CLI v2.13 or above
  • Node.js v10 or above

This addon requires ember-concurrency v2.0.0-rc.1 or higher. If you're using an earlier version of ember-concurrency and/or using ember-concurrency-decorators, you may use ember-concurrency-async < 1.0.0.

Installation

ember install ember-concurrency-async

Usage

Any async methods annotated with one of the task decorators, that is @task, @restartableTask, @dropTask, @keepLatestTask or @enqueueTask, will be transformed into a generator function.

Note that this transformation happens at build time and only works if it can statically determine an async method is an ember-concurrency task. If does so by looking at the decorators applied to an async method and try to determine if they matches one of the known task decorator imports. For example, these would work:

import { task } from 'ember-concurrency';

class Foo {
  @task({ restartable: true }) async foo() {
    // ...
  }
}
import { restartableTask } from 'ember-concurrency';

class Foo {
  @restartableTask async foo() {
    // ...
  }
}
import { enqueueTask as enqueued } from 'ember-concurrency';

class Foo {
  @enqueued async foo() {
    // ...
  }
}
import * as ec from 'ember-concurrency';

class Foo {
  @ec.dropTask async foo() {
    // ...
  }
}

However, these won't:

import { restartableTask } from 'ember-concurrency';

const restartable = restartableTask;

class Foo {
  @restartable async foo() {
    // ...
  }
}
import { enqueueTask, dropTask } from 'ember-concurrency';

function enqueueOrDrop() {
  if (Ember.testing) {
    return dropTask();
  } else {
    return enqueueTask();
  }
}

class Foo {
  @enqueueOrDrop async foo() {
    // ...
  }
}
import * as ec from 'ember-concurrency';

class Foo {
  @ec[Ember.testing ? 'dropTask' : 'enqueueTask'] async foo() {
    // ...
  }
}

If you encountered use cases that you believe should work but doesn't, please open an issue.

TypeScript

ember-concurrency 1.2 and above comes with type definitions. If you are using TypeScript (or the JavaScript Language Server powered by TypeScript), you may want to add the following import in types/<app name>/index.d.ts:

import 'ember-concurrency-async';

This augments ember-concurrency's type definitions to add support for async task functions. See index.d.ts.

If you are using ember-concurrency-ts, you may also need to add:

import 'ember-concurrency-ts/async';

Usage with taskFor at assignment

ember-concurrency-ts provides a taskFor utility function for casting task functions to the correct type. taskFor can be used at assignment and is compatible with ember-concurrency-async:

import { task } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';

class Foo {
  bar: Promise<void>;

  @task
  myTask = taskFor(async function(this: Foo) {
    await this.bar;
  });
}

This also works with async arrow functions, eliminating the need to type this:

import { task } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';

class Foo {
  bar: Promise<void>;

  @task
  myTask = taskFor(async () => {
    await this.bar;
  });
}

Note that async arrow functions are transformed to non-arrow generator functions (arrow generator functions have been proposed but no Babel plugin exists for them at this time). The this context is bound, however, by the @task decorator, so this inside the async function will still refer to the containing class at runtime.

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.