Skip to content
This repository has been archived by the owner on Feb 19, 2018. It is now read-only.

CS2 Discussion: Features: Shorter syntax for defining promises and async/await #60

Closed
mitar opened this issue Dec 12, 2016 · 8 comments
Closed

Comments

@mitar
Copy link

mitar commented Dec 12, 2016

I believe CoffeeScript could have a simpler syntax to use async/await. With #10 and jashkenas/coffeescript#3757 initial support for that was merged in, but I think more could be done.

Here are some my previous thoughts on the subject, but here I am proposing another iteration of those thoughts.

I see three issues with current async/await and promises state in JavaScript:

  1. we had callback hell, now we have new Promise (resolve, reject) => hell
  2. having to think which function is async and which is not and then use wait properly (CoffeeScript makes it defining easier by adding async keywords automatically to functions if they use await, but then it is harder to know when should one call a function with await)
  3. have code full of await keywords around

To address the point 1. I would suggest the ~> operator for defining functions which return a promise:

fetch = (url) ~>
  request url, (error, response, body) ->
    resolve error if error
    reject body

Would be compiled into:

var fetch;
fetch = function(url) {
  return new Promise(function (resolve, reject) {
    request(url, function(error, response, body) {
      if (error) {
        reject(error);
        return;
      }
      resolve(body);
      return;
    });
  });
};

I am not sure if ~> should bind this or not, I think it probably should inside another function, and not for class methods. resolve and reject would be forbidden to define by the developer inside ~> function. Calling resolve or reject always returns. If you do not want to do that, you should use new Promise manually.

If you simply want to create a promise, and not a function which returns a promise, you can do:

google = do ~>
  request 'https://www.google.com', (error, response, body) ->
    resolve error if error
    reject body

So google now is a promise with content of Google's home page.

The reason why ~> is a function which returns a promise and not just returns a promise is so that it is clear that it does not call start the promise, but that you have to call it, to start it. But we could also use ~> as a shorthand for new Promise only.

Anyway, we still have await all around the code. For that I suggest we further extend ? operator. We already use it to be able to say "if this is a function, call it", we can also say "if this is a Promise, await it".

Currently, the following:

fetch?()

Gets compiled into:

if (typeof fetch === "function") {
  fetch('https://www.google.com');
}

And I suggest it gets turned into:

var temp;
if (typeof fetch === "function") {
  temp = fetch('https://commons.tnode.com');
  if (temp && typeof temp.then === "function") {
    await temp;
  }
}

The side-effect of this change would be that using ? in a function would make then all functions aync? Hmm. Maybe we need another symbol for this. But I would love to have a symbol which would call a function as await with something shorter than await.

I really think caller should not care how is a function implemented. So that they can just call a function and get the result, async or not.

What would be a drawback of making all functions async?

@DomVinyard
Copy link

What would be a drawback of making all functions async?

Good question, I have a couple too... are resolve and reject the best options? Could return and throw be repurposed?

@mitar
Copy link
Author

mitar commented Dec 12, 2016

Could return and throw be repurposed?

I was thinking about that as well. The issue is that what if there are some nested normal functions defined inside of a ~> ? How you know if you are resolving outside function or just returning inside one?

@DomVinyard
Copy link

Under your proposal, every function resolves doesn't it?

@mitar
Copy link
Author

mitar commented Dec 13, 2016

No, why would it?

@DomVinyard
Copy link

I really think caller should not care how is a function implemented. So that they can just call a function and get the result, async or not.

If all functions are async, all functions must resolve, no?

@mrmowgli
Copy link

@mitar: I really like your proposal for promises, especially since this is a very common paradigm!

fetch = (url) ~>
  request url, (error, response, body) ->
    resolve error if error
    reject body

By default I think we should avoid adding keywords like async/await for every function as a default. Perhaps we can split each of these feature requests into it's own issue?

@mitar
Copy link
Author

mitar commented Dec 14, 2016

If all functions are async, all functions must resolve, no?

Or reject, which then await turns into an exception.

@coffeescriptbot coffeescriptbot changed the title Shorter syntax for defining promises and async/await CS2 Discussion: Features: Shorter syntax for defining promises and async/await Feb 19, 2018
@coffeescriptbot
Copy link
Collaborator

Migrated to jashkenas/coffeescript#4953

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants