{"action":"created","issue":{"url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/40","labels_url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/40/labels{/name}","comments_url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/40/comments","events_url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/40/events","html_url":"https://github.com/tc39/ecmascript-asyncawait/issues/40","id":69461752,"number":40,"title":"Proposal: Adapt return value to different Promise implementations","user":{"login":"dfahlander","id":6791329,"avatar_url":"https://avatars.githubusercontent.com/u/6791329?v=3","gravatar_id":"","url":"https://api.github.com/users/dfahlander","html_url":"https://github.com/dfahlander","followers_url":"https://api.github.com/users/dfahlander/followers","following_url":"https://api.github.com/users/dfahlander/following{/other_user}","gists_url":"https://api.github.com/users/dfahlander/gists{/gist_id}","starred_url":"https://api.github.com/users/dfahlander/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dfahlander/subscriptions","organizations_url":"https://api.github.com/users/dfahlander/orgs","repos_url":"https://api.github.com/users/dfahlander/repos","events_url":"https://api.github.com/users/dfahlander/events{/privacy}","received_events_url":"https://api.github.com/users/dfahlander/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2015-04-19T20:34:59Z","updated_at":"2015-04-20T21:12:07Z","closed_at":null,"body":"It would be a good thing if async functions would return the same type of promise that was awaited on in their function bodies. This would align with how typescript is implementing it (according to [this issue](https://github.com/Microsoft/TypeScript/issues/1664)). The async/await keywords could then be used together with various promise implementations without loosing the bells and whistles that comes with various Promise libraries such as bluebird, Q, WinJS and Dexie.\r\n\r\nExternal Promise implementations can have features that would be lost if converting them to the 'standard' Promise as suggested in the readme of this repository.\r\n\r\nTherefore, I would propose a more adaptive implemetation of spawn() that can accept and forward any A+ compatible Promise that was awaited for:\r\n\r\n```js\r\nfunction spawn(genF, self) {\r\n    var gen = genF.call(self);\r\n    function step(nextF,initial) {\r\n        var next = nextF();\r\n        if (next.done) {\r\n            // finished with success, resolve the promise\r\n            return initial ?\r\n\r\n                // Nothing was awaited. Direct return value must be converted\r\n                // to promise:\r\n                Promise.resolve(next.value) :\r\n\r\n                // Return the value as is and let the promise\r\n                // implementation take care of the A+ compatible promise chain\r\n                next.value;\r\n        }\r\n        // not finished, chain off the yielded promise and `step` again\r\n        if (!next.value || typeof next.value.then !== 'function')\r\n            // Don't accept yielding a non-promise such as \"yield 3;\".\r\n            // By not accepting that, we could detect bugs better.\r\n            gen.throw(new TypeError(\"Only acceptable to yield a Thenable\"));\r\n\r\n        return next.value.then(function (v) {\r\n            step(function () { return gen.next(v); });\r\n        }, function (e) {\r\n            step(function () { return gen.throw(e); });\r\n        });\r\n    }\r\n\r\n    try {\r\n        step(function() { return gen.next(undefined); }, true);\r\n    } catch (e) {\r\n        // Failure before code has yielded any Promise.\r\n        return Promise.reject(e);\r\n    }\r\n}\r\n```\r\n\r\nSpecifically, for my library, [Dexie.js](https://github.com/dfahlander/Dexie.js), there is a feature that enables 'Promise-Specific Data' which is analogue to 'thread static data' for promises. The entire Dexie API depends on that feature because it enables things like reentrant mutexes, implicit transaction scope, sub transaction awareness and some more API sugar. I believe that bluebird, Q, WinJS and others also would benefit from having this openess in how async/await behave.\r\n\r\nBy not binding the async keyword to a specific implementation of Promise, we would allow new Promise implementations with features that we cannot think of today and still use them with async/await.\r\n"},"comment":{"url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/comments/94569494","html_url":"https://github.com/tc39/ecmascript-asyncawait/issues/40#issuecomment-94569494","issue_url":"https://api.github.com/repos/tc39/ecmascript-asyncawait/issues/40","id":94569494,"user":{"login":"bterlson","id":11236,"avatar_url":"https://avatars.githubusercontent.com/u/11236?v=3","gravatar_id":"","url":"https://api.github.com/users/bterlson","html_url":"https://github.com/bterlson","followers_url":"https://api.github.com/users/bterlson/followers","following_url":"https://api.github.com/users/bterlson/following{/other_user}","gists_url":"https://api.github.com/users/bterlson/gists{/gist_id}","starred_url":"https://api.github.com/users/bterlson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bterlson/subscriptions","organizations_url":"https://api.github.com/users/bterlson/orgs","repos_url":"https://api.github.com/users/bterlson/repos","events_url":"https://api.github.com/users/bterlson/events{/privacy}","received_events_url":"https://api.github.com/users/bterlson/received_events","type":"User","site_admin":false},"created_at":"2015-04-20T21:12:07Z","updated_at":"2015-04-20T21:12:07Z","body":"This is an interesting idea but I'm not sure how well it would work in practice. I think this is morally equivalent to passing through promises returned from then handlers, and has the same issue. Namely, if you think about the following code:\r\n\r\n```\r\nasync function get(url) {\r\n    if(cache[url]) return cache[url];  // no promise returned, so wrapped in built-in promise\r\n    let data = await $.get(url);\r\n    if(!url.endsWith('.json')) return data; // jQuery promise returned\r\n    return await handleJSON(data); // whatever kind of promise handleJSON returns\r\n}\r\n```\r\n\r\nDepending on how you call get, you get a different promise. Today libraries use many different promise libraries so this problem will be quite pervasive. Worse, it seems like it will be very difficult to debug/work around when you need to. Thoughts?"}}