Skip to content

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

@coffeescriptbot

Description

@coffeescriptbot

From @mitar on 2016-12-12 03:53

I believe CoffeeScript could have a simpler syntax to use async/await. With coffeescript6/discuss#10 and #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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions