GithubHelp home page GithubHelp logo

wagenet / ember-concurrency-async Goto Github PK

View Code? Open in Web Editor NEW

This project forked from chancancode/ember-concurrency-async

0.0 0.0 0.0 254 KB

Async task functions for ember-concurrency

Home Page: http://ember-concurrency.com/docs/typescript

License: MIT License

JavaScript 95.11% HTML 4.76% Handlebars 0.13%

ember-concurrency-async's Introduction

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-decorators';

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-decorators';

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

Installation

ember install ember-concurrency-async

Usage

This addon requires the ember-concurrency-decorators addon. 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-decorators';

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

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

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

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

However, these won't:

import { restartableTask } from 'ember-concurrency-decorators';

const restartable = restartableTask;

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

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

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

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-decorators';
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-decorators';
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.

ember-concurrency-async's People

Contributors

chancancode avatar jamescdavis avatar ember-tomster avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.