{"action":"created","issue":{"url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/15","repository_url":"https://api.github.com/repos/tc39/proposal-async-iteration","labels_url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/15/labels{/name}","comments_url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/15/comments","events_url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/15/events","html_url":"https://github.com/tc39/proposal-async-iteration/issues/15","id":122078219,"number":15,"title":"Where should value unwrapping be performed?","user":{"login":"zenparsing","id":5995084,"avatar_url":"https://avatars.githubusercontent.com/u/5995084?v=3","gravatar_id":"","url":"https://api.github.com/users/zenparsing","html_url":"https://github.com/zenparsing","followers_url":"https://api.github.com/users/zenparsing/followers","following_url":"https://api.github.com/users/zenparsing/following{/other_user}","gists_url":"https://api.github.com/users/zenparsing/gists{/gist_id}","starred_url":"https://api.github.com/users/zenparsing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zenparsing/subscriptions","organizations_url":"https://api.github.com/users/zenparsing/orgs","repos_url":"https://api.github.com/users/zenparsing/repos","events_url":"https://api.github.com/users/zenparsing/events{/privacy}","received_events_url":"https://api.github.com/users/zenparsing/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":42,"created_at":"2015-12-14T16:28:13Z","updated_at":"2016-09-16T23:55:31Z","closed_at":null,"body":"In #8, we agreed that when you yield a promise:\r\n\r\n```js\r\nasync function* g() {\r\n    yield new Promise(...);\r\n}\r\n```\r\n\r\nThe promise should be unwrapped before being returned to the consumer.\r\n\r\nIn that thread, we implicitly agreed that within async generators, `yield x` should evaluate like `yield await x`:  in other words, the value is unwrapped on the producer side.  This seems good.\r\n\r\nHowever, we can still manually create an async iterator that returns iteration results where the value component is a promise.\r\n\r\n```js\r\nlet manualAsyncGen = {\r\n    async next() {\r\n        return { value: timeoutPromise(\"Hello world\", 500), done: false };\r\n    },\r\n    [Symbol.asyncGenerator]() { return this },\r\n};\r\n```\r\n\r\nIf I `for-await` such a iterator, should we attempt to unwrap the value component on the consumer side?\r\n\r\n```js\r\nfor await (let value of manualAsyncGen) {\r\n    console.log(value); // a promise or \"Hello world\"?\r\n}\r\n```\r\n\r\nRelated to this, what happens if I `for-await` over a synchronous iterator which contains a list of promises?\r\n\r\n```js\r\nlet list = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];\r\nfor await (let value of list) {\r\n    console.log(value); // A promise or a number?\r\n}\r\n```\r\n\r\nThe basic question here is:  where should we perform the value unwrapping?\r\n\r\n1. On the producer side (in the yield syntax).\r\n1. On the consumer side (in `for-await` and `yield *`).\r\n1. Both.\r\n\r\n\"Both\" seems ideal from the point of view of the consumer, but seems excessive in terms of rescheduling continuations on the job queue. \r\n\r\nIf we do it just on the producer side, then we'll want to create a more complicated sync-to-async iterator conversion algorithm, such that values coming from the sync iterator are property unwrapped.\r\n\r\nIf we do it just on the consumer side, then users wanting to manually call `next`, etc, will have to take care to unwrap any promises in the \"value\" component."},"comment":{"url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/comments/247734188","html_url":"https://github.com/tc39/proposal-async-iteration/issues/15#issuecomment-247734188","issue_url":"https://api.github.com/repos/tc39/proposal-async-iteration/issues/15","id":247734188,"user":{"login":"domenic","id":617481,"avatar_url":"https://avatars.githubusercontent.com/u/617481?v=3","gravatar_id":"","url":"https://api.github.com/users/domenic","html_url":"https://github.com/domenic","followers_url":"https://api.github.com/users/domenic/followers","following_url":"https://api.github.com/users/domenic/following{/other_user}","gists_url":"https://api.github.com/users/domenic/gists{/gist_id}","starred_url":"https://api.github.com/users/domenic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/domenic/subscriptions","organizations_url":"https://api.github.com/users/domenic/orgs","repos_url":"https://api.github.com/users/domenic/repos","events_url":"https://api.github.com/users/domenic/events{/privacy}","received_events_url":"https://api.github.com/users/domenic/received_events","type":"User","site_admin":false},"created_at":"2016-09-16T23:55:30Z","updated_at":"2016-09-16T23:55:30Z","body":"@blesh No problem. The reason is that you want to be able to yield more than just promises. E.g. consider:\r\n\r\n```js\r\nasync function* delayedSequence() {\r\n  yield 1;\r\n  await delay(100);\r\n  yield 2;\r\n}\r\n```\r\n\r\nit would be unfortunate to require `yield await 1` (which is implicitly `yield await Promise.resolve(1)`) when all you're trying to do is yield out a value."}}
{"actor":{"display_login":"domenic"}}