Igor Baklan (2017-01-12T14:22:04.000Z)
io.baklan at gmail.com (2017-01-12T14:23:55.469Z)
Assuming analogy in tuples ([``function*``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), [``yield``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield), [``Generator.prototype.return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return), [``Generator.prototype.throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) ) and ([``async function``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function), [``await``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await), ``?Promise.prototype.return()``, ``?Promise.prototype.throw()``), it would be good to have ``Promise.prototype.return()`` and ``Promise.prototype.throw()`` which in case of ``async``/``await`` function should just "inject" some [``return``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return)/[``throw``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw) action in place of pending ``await`` statement. While for ``.then``-like promises it should just force promise to abnormal completion (with provided result) without calling callbacks provided in .``then``/.``catch`` methods (if they was not yet called before, at the time of "abruption" attempt). In case of general [``new Promise(promiseExecutor)``]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)-like promises it supposedly should work in following manner: some ``abnormalReturn`` / ``abnormalThrow`` signals should be sent to [``promiseExecutor``]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters), then [``promiseExecutor``]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) can handle this signal and initialte "``preventDefault`` behavior" which will correspond to ``catch``/``finally`` blocks capabilities, or [``promiseExecutor``]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) can ignore and not handle this signals, then default behavior should be invoked (which will lead to promise abnormal completion with value provided in ``Promise.prototype.return(...)``/``Promise.prototype.throw()`` call) - this second option will correspond to that case when assumptive meta-code of [``promiseExecutor``]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) does not contain imaginary ``catch``/``finally`` blocks. In code that last case might look like this: ```js const waitAsync = (delay) => (new Promise( (setOk, setErr, signalsSource) => { const beforeComplete = () => {clearTimeout(tid);} const tid = setTimeout( () => {beforeComplete(); setOk();}, delay ); signalsSource.on( "abnormalReturn", (abnormalReturnSignal) => { if (abnormalReturnSignal.value < 5) { // reject offered for abnormal rerun value when it < 5 abnormalReturnSignal.preventDefault(); return; } // do some finally-like cleanup assuming that // abnormalReturnSignal default behavior will be launched beforeComplete(); ); signalsSource.on( "abnormalThrow", (abnormalThrowSignal) => { if (abnormalThrowSignal.value instanceof HatedError) { // catch and reject HatedError-es, corresponds to catching this one // and re-throwing/propagating anything else by abnormalThrowSignal default behavior abnormalThrowSignal.preventDefault(); return; } // do some finally-like cleanup assuming that // abnormalThrowSignal default behavior will be launched beforeComplete(); ); } )); // waitTask = waitAsync(100); // waitTask.then((value) => {console.log(`wait ok, value = ${value}`)}); // waitTask.return(3); - abnormal return should be rejected by promice executor logic, since 3 < 5 // waitTask.return(103); - abnormal return should happen since !(103 < 5) and default behavior should work // "wait ok, value = 100" message should be printed, without delay in 100ms ``` In case if some transpiler decide to implement ``async function``s using [generator functions]((https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*)) this ``promise.return(...)`` and ``promise.throw(...)`` functions can be obtained almost out-of-the-box using [``Generator.prototype.return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) and [``Generator.prototype.throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw). Approximately it might look like: ```js var someFunctionToTranslate = function (...args) { // ... some code here ... var someValue = await somePromice; // ... some code here ... }; ``` might be translated to ```js var someFunctionToTranslate = _rawGeneratorFuncToNormalAsyncLikeFunc(function* (...args) { // ... some translated code here ... var _tmpAwaitTask = new AwaitTask(somePromice); yield _tmpAwaitTask; var someValue = _tmpAwaitTask.awaitResult; // ... some translated code here ... }); ``` Then ``promice.return(...)`` on obtained promise should cause ``generator.return(...)`` on underling generator object, and lead to abnormal completion delivered through ``yield`` instruction which here represents a part of ``await`` statement translation. By the way during my reading of [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) and [``Generator#throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) after reading [bluebirdjs-cancellation]( http://bluebirdjs.com/docs/api/cancellation.html) I've suddenly aware that native ``return`` statement can be "completely rejected" by the means of ``finally`` block, meaning that in general for example there are no 100%-guaranties that [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) will force generator to stop iterating same as there are either no guaranties that [``Generator#throw()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/throw) will force generator to stop (but this one is more obvious regarding ``catch`` statement natural behavior). Here is some patched example from [``Generator#return()``](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) ```js function* gen() { // shielded yield 1 do { try { yield 1; } finally{ continue; } } while (false); // shielded yield 2 do { try { yield 2; } finally{ continue; } } while (false); // shielded yield 3 do { try { yield 3; } finally{ continue; } } while (false); } var g = gen(); console.log(g.next()); // { value: 1, done: false } console.log(g.return("foo")); // { value: 2, done: false } // impudent generator rejects return console.log(g.return("bar")); // { value: 3, done: false } // impudent generator rejects return console.log(g.next()); // { value: undefined, done: true } // generator finishes by its own will ``` So considering this possibility, I would say, in case if ``promise.return()`` would be implemented, provide possibility to [promiseExecutor]( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters) to intercept and override ``.return()`` action is quit natural (assuming that by default it will not handle that signals and not ``preventDefault`` on it, and that means - in general work like regular code without ``finally``/strange-``finally`` blocks)