10 ms·
The moment I started using async await (with babel) combined with the new fetch API so many libraries got obsolete. Getting data is as easy as: async functi
by tanto 10y ago
The moment I started using async await (with babel) combined with the new fetch API so many libraries got obsolete.
Getting data is as easy as:
async function main () {
try {
const res = await fetch('https://api.github.com/orgs/facebook');
const json = await res.json();
console.log(json);
} catch (e) {
// handle error
}
}
So I am quite happy when this lands in modern browsers asap.
- startling 10y agoIs the syntax composable? Can I do const json = await (await fetch(https://api.github.com/orgs/facebook')).json(); or do I have to name it?
- bsou 10y agoyeah that works, your statement is fine
- startling 10y agonice, thanks!
- smilekzs 10y agoWhat you asked for is whether `await` is idempotent. No it isn't. The "argument" to `await` is a Promise, and the "return value" of it is the resolved value of the Promise (i.e. `Promise#then`). EDIT: I missed the `.json()` part, but I suppose it doesn't return a Promise, no?
- tanto 10y agoactually .json() returns a Promise. The first fetch only returns HTTP status code and some other details. The content itself is streamed. You can also access the stream if you want too. In general you would rather just call .json() and get the parsed data. The fetch function can for example also be used to get images. There you would use .blob() and assign that to an image.src with URL.createObjectURL(blob); See here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/U...
- startling 10y agoThis is totally not what I'm asking, thanks.
- dvlsg 10y agoYou probably can, but you may as well just do this instead: const json = await fetch('https://api.github.com/orgs/facebook').then(res => res.json());
- ludamad 10y agoI think the await code is more explicit, whereas a callback is somewhat ambiguous
- nathancahill 10y agoI'll be glad to do away with callbacks completely tbh.
- grandalf 10y agoyes code like that works.
- tigershark 10y agoI don't understand your code. the .json() should be inside the parentheses because you cannot await something that has already been converted from a Promise to a real value. And even in that case that code will be exactly equivalent to the synchronous code because you are awaiting in place the result of the Promise. So, given my very limited knowledge of javascript, I think that probably you can write it moving the .json() inside, but I don't see why you would ever want to do it if you can have the same result without the await boilerplate... EDIT: got it, you want to do it inside an aync function with some other code after the await, then I think it makes sense in that case.
- deleted 10y ago[deleted]
- neoeldex 10y agofetch() returns a promise, which is unwrapped using await. fetch's promise contains a response object, which has a json method, which returns a promise. const responsePromise = fetch(https://api.github.com/orgs/facebook'); const response = await responsePromise; const jsonPromise = response.json(); const json = await jsonPromise;
- nailer 10y agoTip: if you use anything other than fetch you'll just get JSON back immediately based on the MIME type, without the unnecessary conversion step.
- tehbeard 10y agoThose other than fetch()s still do the "unnecessary conversion step". Don't dismiss fetch by the fact it doesn't hand hold or make assumptions. It should be said that fetch() is quite low level call compared to what we've had before regarding ajax, so it makes sense in larger projects to wrap it to keep any logging, error handling and retry in one place.
- nailer 10y ago> it doesn't hand hold or make assumptions Using MIME types isn't hand holding or making an assumption. Yes, people who need the low level features will wrap it with a series of competing high level libraries. It's a missed opportunity to make a standard, capable high level API though.
- moron4hire 10y agoFetch API also doesn't have any means of tracking progress, making it strictly inferior to XmlHTTPRequest
- neoeldex 10y agoFetch does have streaming uploads and downloads, and a quite some other features which doesn't come with xmlHttpRequest. Making it not strictly inferior to XMLHttpRequest
- moron4hire 10y agoWill have. Future tense. Not present tense.
- 10y ago
- ludamad 10y agoWith this natively in V8 the debug experience ought to be much better than now, too
- foota 10y agoIs using async/await through babel a good idea? When I last looked at it I thought it was using a busy loop which didn't seem like such a great idea to use in shipping code.
- tlrobinson 10y agoIt's fine. It transforms async functions into a state machine.
- nostrademons 10y agoIt's okay but clumsy. It's a state machine, not a busy loop, but the compiled code is a lot more verbose than the input code (and so you pay a latency penalty on the client). The developer experience is also sub-par: you'll get regenerator stack frames in any of your stack traces, and it interacts poorly with babel-watch. You can do it, it's not insane, but native async/await will be much, much nicer.
- tlrobinson 10y agoCan you elaborate on "it interacts poorly with babel-watch."?
- nostrademons 10y agoIIRC under babel-watch it required me to include babel-polyfill at the top of my main script, but under babel-node it prevented me from including babel-polyfill at the top of my main script. (babel-polyfill has a check so that it can only be required once, and errors out otherwise.) That meant I needed to keep commenting/uncommenting that line when I wanted to debug things. There were also cases where I wasn't sure if babel-watch was reloading dependencies properly if I used async code in a file, which is why I had to keep switching to babel-node or running the code through babel and inspecting the generated code to debug. Overall, it just felt very new and unpolished (which I guess it was...I was working with it around March, so babel-watch was < 1 month old and babel async/await was about 2-3 months at the time) to be relying on all the time.
- deleted 10y ago
- viperscape 10y agoThe try and catch inside the async function is also great. Curious though, is using const over let common? I usually use const for imports and module level globals, and let inside functions. I recently got back into javascript, and it's nice to see it flourishing.
- bb85 10y agoThe great thing about let and const, for me, is that it gives you crucial information about variables without having to look further down. const should be the default, and if you're going to reassign it, then use let. In most code, you'll use const on the vast majority of variables, and it'll make let assignments stick out, which helps a lot when you're browsing the code or refactoring.
- spraak 10y agoThis right here. One of my friends (a more experienced developer) told me at coffee one day, "I use const for everything" which really stuck with me. It really helps make it clear if you need a mutation to have let stand out.
- rpastuszak 10y agoHowever, it's worth noting that using const doesn't make variables immutable. It only protects them of being reassigned: const val = 'a'; val = 'b'; // TypeError const obj = { val: 'a' }; obj.val = 'b'; // This line will still work. obj = { val: 'b' }; // TypeError
- dfischer 10y agoWhat do you use for the new fetch api on node?
- mikeryan 10y agoI don't use it on Node but this syntax is great on react native.
- pitaj 10y agoProbably [node-fetch](https://www.npmjs.com/package/node-fetch https://www.npmjs.com/package/node-fetch)
- ascagnel_ 10y agonode-fetch is one option, but I go with isomorphic-fetch[0] (since it can be run client-side via Babel). [0] https://github.com/matthew-andrews/isomorphic-fetch https://github.com/matthew-andrews/isomorphic-fetch
- danielstocks 10y agofyi isomorphic-fetch is just a universal wrapper around node-fetch and github-fetch
- tomp 10y agoCan anyone point to a good explanation why this is preferable to cooperative threads (coroutines)? I.e. the above code could easily be written as function main() { try { const res = fetch('https://api.github.com/orgs/facebook'); // yield here const json = res.json(); // yield here console.log(json); } catch (e) { // handle error } } and the runtime would automatically yield this coroutine and let other coroutines run whenever some call blocks. I guess the only realy difference would be that I would make `await` (and `async`) implicit, similar to how exceptions are handled implicitly in the above snippet (i.e. we don't annotate functions as `throwing` and we don't use an `attempt` statement (analogous to `await`) when calling `throwing` functions). Edit: Reading various articles, the best explanation is that since the single-threaded nature of JavaScript makes synchronisity implicit (i.e. all code is run in an implicit transaction), it has to make asynchronisity explicit. The alternative would be to have coroutines/fibres (implicit asynchronisity), but with explicit `atomic` blocks (for synchronisity). C# doesn't provide any synchronisity guarantees, so I guess the motivations there were different (it's really hard (impossible?) to implement fibres efficiently, and even harder to allow for native code interoperability).
- turblety 10y agoIt might be something to do with backwards compatibility.
- tomp 10y agoWhat do you mean? Edit: I mean, can you give any examples of how old code would be broken by implementing something like this?
- amelius 10y agoPerhaps this is the reason: Is it possible to have a yield inside a called function (i.e., not the generator function itself)? Last time I checked this was not allowed (?) Anyway, if so, I would strongly prefer this over a async/await construct, which is less general.
- Kiro 10y agoWhy do you need to put await before res.json?
- tomelders 10y agoSomeone correct me if I'm wrong here, this is just my hunch - but according to the fetch spec, res.json returns a promise, which are async. I'm assuming so you have the chance to handle errors as a result of malformed JSON.
- thomasahle 10y agoPromises are used for catching errors?
- onestone 10y agoYes.
- jwmerrill 10y agoAt the time that the request resolves, it has received and processed the response headers, but it may still be receiving the response body (which is represented as a stream). All the body representations (like .text() or .json()) need to wait until the body has arrived before they can resolve. https://fetch.spec.whatwg.org/#concept-body-consume-body https://fetch.spec.whatwg.org/#concept-body-consume-body
- deleted 10y ago[deleted]