Proposal: use "One More Point" to handle async functions

# Li Xiaolong (8 years ago)

The traditional callback method to handle async is not elegant and clear. Even the promised style is kind of odd. So I got an idea that we use "One More Point"(OMP) to make async coding easier to use. For example:


//Without One More Point:

function async(args, callback) {

         ...

         obj.doSomeThing(function(result) {

                   obj2.doSomeOtherThing(result, function(result2){

                            callback(result2);

})

         });

}

async([1,2,3], function(result) {

         alert(result);

.

});

 

 

//With the help of One More Point:

function async(args) {

         ...

         .return obj2..doSomeOtherThing(obj..doSomeThing());

}

alert(.async([1,2,3]));

.

So, in general, the OMP makes async coding looks like sync coding. The return value of a function called with OMP will return the value after the ".return" keyword. The code after the OMP call will all be delayed until the async ends. This sounds like the code is blocked, but actually it's non-blocking, as the user can still interact with the interface and the cpu is sleeping. There is one limitation that OMP style can only replace callback style async calls that are at the end of a function, since there is no more code after the async function is called. However, as far as I can see, about half or more async functions are at the end of a function. So, the OMP is significant.

# Bergi (8 years ago)

What you call "one more point" already exists as the await keyword and is much more powerful than a limited .return operator: tc39/ecmascript-asyncawait

Please make sure to be familiar with the topic before making further proposals.

# Li Xiaolong (8 years ago)

Sorry I'm not familiar with es7. But I still thing my OMP is better than async/await.

1: the await keyword can only be used in an async function, so each time you want to await you have to add async before outer function.

2: async/await still use promise to handle async, which is not as clear as my OMP that only use functions. The reject state of the promise became redundant since await never gets it.

3: the async function calls identically with sync functions, makes it hard to check out if the function is async without jumping to the definition. But OMP can easily be recognized.

4: it's complex for async/await to handle deep async callbacks.

# Caitlin Potter (8 years ago)

On Sep 27, 2016, at 5:23 PM, Li Xiaolong <898310778 at outlook.com> wrote:

Sorry I’m not familiar with es7. But I still thing my OMP is better than async/await. 1: the await keyword can only be used in an async function, so each time you want to await you have to add async before outer function.

That’s not necessarily true — await in modules may be very different from this.

2: async/await still use promise to handle async, which is not as clear as my OMP that only use functions. The reject state of the promise became redundant since await never gets it.

You might be confused about something — if an awaited Promise is rejected, the async function can be resumed from a catch block to handle the rejection.

3: the async function calls identically with sync functions, makes it hard to check out if the function is async without jumping to the definition. But OMP can easily be recognized.

I’m not sure everyone shares this view — many people laud other languages where coroutines (for example) are indistinguishable from regular subroutines.

4: it’s complex for async/await to handle deep async callbacks.

How?

# Li Xiaolong (8 years ago)

That’s not necessarily true — await in modules may be very different from this.

I don’t know what await in modules look like.

You might be confused about something — if an awaited Promise is rejected, the async function can be resumed from a catch block to handle the rejection.

I know await can be catched. But the redundant reject state in promise makes it more confusing.

I’m not sure everyone shares this view — many people laud other languages where coroutines (for example) are indistinguishable from regular subroutines.

Well, when you are debugging and can’t find where the code waits, you’ll miss the OMP.

How?

I thought it again. Can I write: ‘await obj2.doSomeOtherThing(await obj1.doSomeThing())’? If I can, then the await is not more complex than OMP when dealing with deep async, just a little longer.

# Caitlin Potter (8 years ago)

On Sep 27, 2016, at 6:24 PM, Li Xiaolong <898310778 at outlook.com> wrote:

That’s not necessarily true — await in modules may be very different from this.

I don’t know what await in modules look like.

It’s still being discussed. I think there are some strong arguments for top-level “await”, which is the only case where you’re (currently) forced to be in a synchronous mode.

You might be confused about something — if an awaited Promise is rejected, the async function can be resumed from a catch block to handle the rejection.

I know await can be catched. But the redundant reject state in promise makes it more confusing.

What “redundant reject state”? What is redundant? And more importantly, how is it confusing? It maps to the same syntax of typical synchronous code, which is pretty clear about the error state vs non-error state.

I’m not sure everyone shares this view — many people laud other languages where coroutines (for example) are indistinguishable from regular subroutines.

Well, when you are debugging and can’t find where the code waits, you’ll miss the OMP.

That sounds like a puzzle for the DevTools team to solve :) There’s no reason the inspector couldn’t see this.

How? I thought it again. Can I write: ‘await obj2.doSomeOtherThing(await obj1.doSomeThing())’? If I can, then the await is not more complex than OMP when dealing with deep async, just a little longer.

Yes, AwaitExpressions are just a form of UnaryExpression, and can be used anywhere a UnaryExpression is used (including as an operand to a function which is being await-ed.

# Jason Orendorff (8 years ago)

On Tue, Sep 27, 2016 at 10:23 AM, Li Xiaolong <898310778 at outlook.com> wrote:

3: the async function calls identically with sync functions, makes it hard to check out if the function is async without jumping to the definition. But OMP can easily be recognized.

Usually, async calls will be marked with await, which to me seems somewhat easier to spot.

On the other hand it's true that the function call itself is just a function call. One nice consequence is that you can call an async function without immediately blocking and waiting for it to finish. For example,

let p1 = start_download();    // start two things at once
let p2 = start_query();
let file = await p1;    // wait for results
let result = await p2;

Is that possible with OMP syntax?

In your proposal, what would happen if you called an OMP async function (one that ends with a .return) using plain.method() call syntax? What if you call a sync function or method using OMP call syntax?