async/await -> await/async: a simpler, less error-prone async syntax

Naveen Chawla naveen.chwl at gmail.com
Wed Dec 6 09:28:04 UTC 2017


kai, no, that gets less and less manageable as the complexity of the async
flow increases

On Wed, 6 Dec 2017 at 07:19 kai zhu <kaizhu256 at gmail.com> wrote:

> you can avoid this entire debate by using trusty and simple callbacks
> instead.  here's real-world example of using a callback like you would
> async/await, to asynchronously test various states/scenarios for user-login
> in an app (using recursion to avoid callback-hell):
>
> https://github.com/kaizhu256/node-swgg/blob/2017.7.24/test.js#L918
>
> ```js
> local.testCase_userLoginXxx_default = function (options, onError) {
> /*
>  * this function will test userLoginXxx's default handling-behavior
>  */
>     var modeNext, onNext;
>     modeNext = 0;
>     onNext = function (error, data) {
>         modeNext += 1;
>         switch (modeNext) {
>         case 1:
>             // cleanup userJwtEncrypted
>             delete local.userJwtEncrypted;
>             // test userLogout's default handling-behavior
>             options = {};
>             local.userLogout(options, onNext);
>             break;
>         case 2:
>             // validate error occurred
>             local.assert(error, error);
>             // test userLoginByPassword's 401 handling-behavior
>             options = { password: 'undefined', username: 'undefined' };
>             local.userLoginByPassword(options, onNext);
>             break;
>         case 3:
>             // validate error occurred
>             local.assert(error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 401);
>             // validate userJwtEncrypted does not exist
>             local.assert(!local.userJwtEncrypted, local.userJwtEncrypted);
>             // test userLogout's 401 handling-behavior
>             options = {};
>             local.userLogout(options, onNext);
>             break;
>         case 4:
>             // validate error occurred
>             local.assert(error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 401);
>             // validate userJwtEncrypted does not exist
>             local.assert(!local.userJwtEncrypted, local.userJwtEncrypted);
>             // test userLoginByPassword's 200 handling-behavior
>             options = { password: 'secret', username: 'admin' };
>             local.userLoginByPassword(options, onNext);
>             break;
>         case 5:
>             // validate no error occurred
>             local.assert(!error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 200);
>             // validate userJwtEncrypted exists
>             local.assert(local.userJwtEncrypted, local.userJwtEncrypted);
>             // test persistent-session handling-behavior
>             local.apiDict['x-test crudNullGet']._ajax({}, onNext);
>             break;
>         case 6:
>             // validate no error occurred
>             local.assert(!error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 200);
>             // validate userJwtEncrypted exists
>             local.assert(local.userJwtEncrypted, local.userJwtEncrypted);
>             // test userLogout's 200 handling-behavior
>             // test jwtEncoded's update handling-behavior
>             options = { jwtEncrypted: local.jwtA256GcmEncrypt({ sub:
> 'admin' }) };
>             local.userLogout(options, onNext);
>             break;
>         case 7:
>             // validate no error occurred
>             local.assert(!error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 200);
>             // validate userJwtEncrypted exists
>             local.assert(local.userJwtEncrypted, local.userJwtEncrypted);
>             // test userLogout's 401 handling-behavior
>             options = {};
>             local.userLogout(options, onNext);
>             break;
>         case 8:
>             // validate error occurred
>             local.assert(error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 401);
>             // test userLoginByPassword's 400 handling-behavior
>             local.ajax({ url:
> '/api/v0/user/userLoginByPassword?password=1' }, onNext);
>             break;
>         case 9:
>             // validate error occurred
>             local.assert(error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 400);
>             // test userLogout's invalid-username handling-behavior
>             options = { jwtEncrypted: local.jwtA256GcmEncrypt({ sub:
> 'undefined' }) };
>             local.userLogout(options, onNext);
>             break;
>         case 10:
>             // validate error occurred
>             local.assert(error, error);
>             // validate statusCode
>             local.assertJsonEqual(data.statusCode, 401);
>             onError(null, data);
>             break;
>         }
>     };
>     onNext();
> };
> ```
>
> and here’s screenshot of setting a single-breakpoint to easily debug and
> step through all 10 asynchronous switch-statements in the callback.
> you can reproduce the test-case in screenshot with this link:
> https://kaizhu256.github.io/node-swgg/build..beta..travis-ci.org/app/?modeTest=1&modeTestCase=testCase_userLoginXxx_default
>
> -kai
>
>
>
> On Dec 6, 2017, at 6:38 AM, Alexander Jones <alex at weej.com> wrote:
>
> > with the added bonus of transparently allowing sync functions to be
> converted to async functions without fundamentally affecting consumer
> calling code.
>
> It does fundamentally affect calling code if the calling code reaches
> outside of its local variables. The state of the world around you might
> change any time you await and give control back to the event loop.
>
> On Mon, 4 Dec 2017 at 19:16, Naveen Chawla <naveen.chwl at gmail.com> wrote:
>
>> Obviously. The whole point of this proposal is that awaiting async
>> functions is automatically _implied_ inside an `autoasync` function, unless
>> an async function is called with a `background` qualifier (which thereby
>> makes it return its promise instead). The OP is right: this is a far less
>> bug prone way to do async programming than `async` `await`, while offering
>> all its functionality, with the added bonus of transparently allowing sync
>> functions to be converted to async functions without fundamentally
>> affecting consumer calling code.
>>
>> For those who want to be able to do extensive async programming, having
>> this in the language, and using it instead of `await` `async` throughout,
>> is a no-brainer.
>>
>> Of course, I am qualifying that it must be new keywords, not `await`
>> `async` juggled like in the original post, but that wasn't the thrust of
>> the proposal anyway.
>>
>> On Mon, 4 Dec 2017 at 21:09 Isiah Meadows <isiahmeadows at gmail.com> wrote:
>>
>>> Am I misunderstanding something about this proposal that it's
>>> substantially any different from `.then` or immediately invoked async
>>> functions?
>>>
>>> ```js
>>> // Original
>>> await function foo() {
>>>     const bar = async baz()
>>>     use(bar)
>>> }
>>>
>>> // What I'm reading
>>> function foo() {
>>>     ;(async () => {
>>>         const bar = await baz()
>>>         use(bar)
>>>     })()
>>> }
>>> function foo() {
>>>     try {
>>>         Promise.resolve(baz())
>>>         .then(bar => { use(bar) })
>>>     } catch (e) {
>>>         Promise.reject(e)
>>>     }
>>> }
>>> ```
>>>
>>> On Mon, Dec 4, 2017, 09:54 T.J. Crowder <tj.crowder at farsightsoftware.com>
>>> wrote:
>>>
>>>> On Mon, Dec 4, 2017 at 2:37 PM, Bob Myers <rtm at gol.com> wrote:
>>>> >
>>>> > It turns out that this approach has a number of problems.
>>>> > As a result, future versions of selenium will no longer support it.
>>>> > Test writers will be asked to write `await` where needed.
>>>>
>>>> Were there problems other than the complexity of maintaining the
>>>> promise manager tool and issues with debuggability? Neither of those
>>>> seems like it would be an issue with Steven's proposal...
>>>>
>>>> (I just realized for the first time, Bob, that your initials are RTM.
>>>> I love it. You should adopt Frank as a second middle name. ;-) )
>>>>
>>>> -- T.J. Crowder
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171206/bf200a32/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screen Shot 2017-12-06 at 8.35.29 AM.png
Type: image/png
Size: 1533376 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171206/bf200a32/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screen Shot 2017-12-06 at 8.35.29 AM.png
Type: image/png
Size: 1533376 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171206/bf200a32/attachment-0003.png>


More information about the es-discuss mailing list