Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous Iterations #11326

Closed
ivogabe opened this issue Oct 3, 2016 · 4 comments
Closed

Asynchronous Iterations #11326

ivogabe opened this issue Oct 3, 2016 · 4 comments
Assignees
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@ivogabe
Copy link
Contributor

ivogabe commented Oct 3, 2016

The asynchronous iterations proposal is now in stage 3, so it should be safe to support that in TypeScript now. Currently, a function may be a generator or an async function, but it cannot be both. The asynchronous iteration proposal removes this restriction. Here's an example from their readme:

async function* readLines(path) {
  let file = await fileOpen(path);

  try {
    while (!file.EOF) {
      yield await file.readLine();
    }
  } finally {
    await file.close();
  }
}

Types

Generator functions declare several interfaces:

interface IteratorResult<T> {
    done: boolean;
    value: T;
}
interface Iterator<T> {
    next(value?: any): IteratorResult<T>;
    return?(value?: any): IteratorResult<T>;
    throw?(e?: any): IteratorResult<T>;
}
interface Iterable<T> {
    [Symbol.iterator](): Iterator<T>;
}
interface IterableIterator<T> extends Iterator<T> {
    [Symbol.iterator](): IterableIterator<T>;
}

Async generators return promises instead of their IteratorResult, and use a new symbol, Symbol.asyncIterator:

interface IteratorResult<T> {
    done: boolean;
    value: T;
}
interface AsyncIterator<T> {
    next(value?: any): Promise<IteratorResult<T>>;
    return?(value?: any): Promise<IteratorResult<T>>;
    throw?(e?: any): Promise<IteratorResult<T>>;
}
interface AsyncIterable<T> {
    [Symbol.asyncIterator](): AsyncIterator<T>;
}
interface AsyncIterableIterator<T> extends AsyncIterator<T> {
    [Symbol.asyncIterator](): AsyncIterableIterator<T>;
}

Emit

I guess that this would require another helper function to downlevel to ES2015, similar to the one used for async functions. Yield and await expression would both be replaced by yield expression, so they need to be decorated with some tag, like yield ['await', promise] for await promise.

for-await-of

The proposal also introduces a new loop. An example from their readme:

for await (const line of readLines(filePath)) {
  console.log(line);
}

This iterates over the [Symbol.asyncIterator]() object and awaits the value of .next(), similar to a for-of loop. This loop can only be used in async functions.

@mhegazy mhegazy added Suggestion An idea for TypeScript ES Next New featurers for ECMAScript (a.k.a. ESNext) In Discussion Not yet reached consensus labels Oct 21, 2016
@appsforartists
Copy link

FWIW, TypeScript currently emits garbage if you try to for await. Same code works in Babel

I'd expect it to throw an error until async iteration is properly supported.

@mhegazy
Copy link
Contributor

mhegazy commented Nov 14, 2016

I'd expect it to throw an error until async iteration is properly supported.

it does.

animation

@mhegazy mhegazy added this to the TypeScript 2.2 milestone Dec 8, 2016
@mhegazy mhegazy added Committed The team has roadmapped this issue and removed In Discussion Not yet reached consensus labels Dec 23, 2016
@mhegazy mhegazy modified the milestones: TypeScript 2.2, TypeScript 2.3 Feb 2, 2017
@imetallica
Copy link

imetallica commented Feb 10, 2017

One suggestion I think can make the asynchronous workflows easier to read:

  • instead of using await, we could do as F# does and use let!, yield! and do!.
    Put the async{} inside instead of outside the function.

For example

function readLines(path) {
  async{
    let! file = fileOpen(path);

    try {
      while (!file.EOF) {
        yield! file.readLine();
      }
    } finally {
      do! file.close(); // Or something else as identifier.
    }
  }
}

@ErikCupal
Copy link

ErikCupal commented Feb 10, 2017

@imetallica Eeh, I don't think it's a good idea.

The main goal of Typescript is to provide type safety and analysis for JS. Therefore, it shouldn't deviate from ECMAScript standard if it is possible.

@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Feb 17, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Committed The team has roadmapped this issue ES Next New featurers for ECMAScript (a.k.a. ESNext) Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants