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)