mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-05 23:43:37 +02:00
feat(resources): split up topics and languages
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
---
|
||||
authors:
|
||||
- "ddivad#0001"
|
||||
- "veksen#1060"
|
||||
created_at: "2019/10/01"
|
||||
updated_at: 2020/05/20
|
||||
title: Async/Await
|
||||
recommended_reading:
|
||||
- javascript/promises/intro
|
||||
---
|
||||
|
||||
## Async/Await
|
||||
|
||||
Async/Await is another way to handle the calling of asynchronous code and is built on top of Promises. It makes it possible to write asynchronous code that feels synchronous.
|
||||
|
||||
**Its usage is equivalent to resolving a promise with `.then()`**.
|
||||
|
||||
It is made up of 2 keywords as the name suggests: `async` and `await`. These need to be used together for this method to work.
|
||||
|
||||
## Async
|
||||
|
||||
The `async` keyword is used to show that the function is going to return a promise. **Any return values from the function will be converted to a promise automatically**, if they are not already.
|
||||
|
||||
```js
|
||||
async function getWeather() {
|
||||
return "sunny";
|
||||
}
|
||||
|
||||
getPromise();
|
||||
// Promise<"sunny">
|
||||
```
|
||||
|
||||
This basic example will return a promise with the value of `getWeather`.
|
||||
|
||||
## Await
|
||||
|
||||
The `await` keyword is used to wait until a promise has executed and fetches the result. In order to use the `await` keyword, you **need** to be inside an `async` function.
|
||||
|
||||
```js
|
||||
async function checkWeather() {
|
||||
const weather = await getWeather();
|
||||
console.log(weather); // "sunny"
|
||||
}
|
||||
```
|
||||
|
||||
This code will call the `getWeather()` function from above and will wait on that line until the promise returned from the `async` function has returned.
|
||||
|
||||
Another example to demonstrate this is if we extended the `getWeather()` function from above to add a 5 second delay.
|
||||
|
||||
```js
|
||||
async function getWeather() {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => resolve("sunny"), 5000);
|
||||
});
|
||||
|
||||
const weather = await promise; // Execution waits here until promise resolves
|
||||
console.log(weather); // "sunny"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
As with Promises, if the Promise returns with an error, it will affect the `await` call that triggered it. When using Promises without Async / Await, the `.catch()` syntax is used, and this also exists with Aysnc / Await using the `try...catch` syntax. This can be demonstrated by making our `foo()` function throw an error.
|
||||
|
||||
```js
|
||||
async function foo() {
|
||||
throw new Error("An Error Occurred");
|
||||
}
|
||||
```
|
||||
|
||||
This would be handled using Aysnc / Await like so:
|
||||
|
||||
```js
|
||||
async function getData() {
|
||||
try {
|
||||
let data = await foo();
|
||||
console.log(data);
|
||||
} catch (err) {
|
||||
console.error(err); // err: An Error Occurred
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Beginner Mistakes
|
||||
|
||||
As mentioned in the [intro](./intro.md), Promises are the highest source of confusion for beginners. Async / Await adds another layer on top of Promises, and comes with its own pitfalls.
|
||||
|
||||
`await` will **only** work if the function you try to add `await` to is `async`. Using `await` in top level code will not work (yet).
|
||||
|
||||
```js
|
||||
let weather = await getWeather(); // syntax error
|
||||
```
|
||||
|
||||
To get around this issue, you can use an declare asynchronous function anonymously, if needed:
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
let weather = await getWeather();
|
||||
console.log(weather); // "sunny"
|
||||
})();
|
||||
```
|
||||
|
||||
Top-Level-Await is something that _may_ get added to Javascript in the future, but for now wrapper functions like above are needed for this functionality.
|
||||
|
||||
## Real World Example
|
||||
|
||||
Here is a real function that gets character information from the Rick and Morty API.
|
||||
You can try it in your browser if you want to test it out.
|
||||
|
||||
```js
|
||||
async function getCharacters() {
|
||||
const response = await fetch(`https://rickandmortyapi.com/api/character`);
|
||||
const data = await response.json();
|
||||
return data.results;
|
||||
}
|
||||
|
||||
// or, mixed
|
||||
async function getCharacters() {
|
||||
const data = await fetch(
|
||||
`https://rickandmortyapi.com/api/character`
|
||||
).then((res) => res.json());
|
||||
return data.results;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
let characters = await getCharacters();
|
||||
console.log(characters); // (20) [{...}, {...}, {...}]
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
In this example, we are querying real data from the Rick & Morty API. This API has a lot of information regarding Rick & Morty, but here, we are trying to retrieve all the characters.
|
||||
|
||||
- The first thing we do is use `fetch` to retrieve the data from the API. `fetch` is a built in function in web browsers to do http requests, and returns a Promise by default. We `await` the result of this.
|
||||
- When we get the result, we need to get the `JSON` value of the data. To do this, the `.json()` method from fetch is used. We then return the results.
|
||||
- As `await` can only be used in an `async` function, we use the method from above to make this work. As `getCharacters()` returns a Promise due to it being `async`, we `await` the result. We surround this in a `try...catch` in case fetch returns an error. Then, if no error is returned, `characters` contains the information we want, and is logged to the console. If `getCharacters()` returns an error, that error is also logged.
|
||||
|
||||
### Let's also look at an example from Discord.js:
|
||||
|
||||
```js
|
||||
client.on("message", (msg) => {
|
||||
if (msg.author.bot) return;
|
||||
|
||||
if (msg.content === "ping") {
|
||||
const message = await msg.channel.send("pong");
|
||||
message.react("⚠️");
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Comparision with default Promises
|
||||
|
||||
Below is the same code implemented without using Async / Await as a comparision. Here, you can see the differences between the two methods, and how Aysnc / Await makes the code appear in a _more synchronous_ pattern, and can be clearer to follow.
|
||||
|
||||
```js
|
||||
function getCharacters() {
|
||||
return fetch(`https://rickandmortyapi.com/api/character`)
|
||||
.then((res) => res.json())
|
||||
.then((res) => res.results);
|
||||
}
|
||||
|
||||
getCharacters()
|
||||
.then((characters) => {
|
||||
console.log(characters); // (20) [{...}, {...}, {...}]
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
authors:
|
||||
- "veksen#1060"
|
||||
created_at: "2020/05/20"
|
||||
title: Converting a callback
|
||||
recommended_reading:
|
||||
- javascript/promises/intro
|
||||
- javascript/promises/async-await
|
||||
---
|
||||
|
||||
It's still pretty common to be forced to use an API that doesn't support promises. While a promise API is often preferred, it's not always available.
|
||||
|
||||
Before anything check:
|
||||
|
||||
- If your library might support both callbacks and API, in the documentation, or README from Github
|
||||
- If there is not another library that does the same thing, but supports promises.
|
||||
|
||||
## From a callback
|
||||
|
||||
Let's look at a conventional, but fictional callback API:
|
||||
|
||||
```js
|
||||
getWeather("Los Angeles", (error, result) => {
|
||||
if (err) throw err;
|
||||
|
||||
console.log(result); // "sunny"
|
||||
});
|
||||
```
|
||||
|
||||
## To a promise
|
||||
|
||||
If we want to use it as a promise, we'll need to wrap a promise around it:
|
||||
|
||||
```js
|
||||
function getWeatherAsync(city) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getWeather(city, (error, result) => {
|
||||
if (err) reject(err);
|
||||
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Which we can now use:
|
||||
|
||||
```js
|
||||
getWeatherAsync("Los Angeles")
|
||||
.then((weather) => {
|
||||
console.log(weather);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
// or using async/await
|
||||
const weather = await getWeatherAsync("Los Angeles").catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
console.log(weather);
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
authors:
|
||||
- "Xetera#0001"
|
||||
- "veksen#1060"
|
||||
created_at: 2019/07/26
|
||||
updated_at: 2020/05/20
|
||||
title: Introduction to Promises
|
||||
recommended_reading:
|
||||
- javascript/callbacks/intro
|
||||
- javascript/es6/arrow-functions
|
||||
---
|
||||
|
||||
## A Promise to Keep
|
||||
|
||||
A `Promise` in Javascript represents an action that has already started, but one that will be
|
||||
completed at a later time. Much like in real life, when you create a promise, you are expected
|
||||
to fulfill that promise. However, sometimes things go wrong where you can no longer fulfill
|
||||
a promise you made. This is essentially the main idea behind how promises work in javascript.
|
||||
|
||||
## Basics
|
||||
|
||||
When you create a Promise or call a function that returns a Promise in Javascript, you're left
|
||||
with an object that can either resolve into the actual value that you were promised, or it
|
||||
can reject and leave you with an error for why that promise failed.
|
||||
|
||||
We can access these values using the `.then` and `.catch` methods on the `Promise` object respectively.
|
||||
|
||||
## A Simple Example
|
||||
|
||||
First, let's explore a bit of a made-up example. Imagine we have a promise-returning function
|
||||
called `getMembers` that retrieves all the members in a discord server. When we execute this
|
||||
function we see the following result.
|
||||
|
||||
```js
|
||||
const members = getMembers("The Programmers Hangout");
|
||||
console.log(members); // Promise {<pending>}
|
||||
```
|
||||
|
||||
Normally, we would have expected to see an array of all the members but it takes time to
|
||||
get all the information about members so we're instead returned a Promise of members, rather
|
||||
than the members themselves.
|
||||
|
||||
In order to access this information, we'll have to call the `.then` method on our `members` object
|
||||
to access the actual members like so.
|
||||
|
||||
```js
|
||||
getMembers("The Programmers Hangout").then((members) => {
|
||||
console.log(members); // (32k) [{...}, {...}, {...}]
|
||||
});
|
||||
```
|
||||
|
||||
This way we are able to make sure that we only try to `console.log` when the `getMembers` function has resolved and ready to be used.
|
||||
|
||||
## Beginner Mistakes
|
||||
|
||||
Promises are possibly the #1 most common source of confusion for beginners. In order
|
||||
to avoid falling in pitfalls yourself, you have to remember 2 things about Javascript when
|
||||
working with promises.
|
||||
|
||||
1. Javascript does not wait.
|
||||
2. No seriously, Javascript won't wait for your promises!
|
||||
|
||||
You may have tried doing something like this before.
|
||||
|
||||
```js
|
||||
// Incorrect code, don't copy!
|
||||
let results;
|
||||
getWeather("Los Angeles").then((weather) => {
|
||||
results = weather;
|
||||
});
|
||||
console.log(results); // undefined
|
||||
```
|
||||
|
||||
Why is `results` undefined? Because **Javascript doesn't wait**. Whenever a Promise is created,
|
||||
your code will continue to run until there's no more code left in the stack. Only then
|
||||
will javascript try to run the `.then` callback of a Promise. Even if your Promise resolves
|
||||
immediately you are going to have to wait until you've run all the code in the stack before
|
||||
your `.then` callback has a chance to start running. This is due to the way the event loop works,
|
||||
you can watch [this amazing talk](https://youtu.be/8aGhZQkoFbQ) on it to learn more.
|
||||
|
||||
In order to fix this problem we need to move the `console.log` inside the `.then` callback like so:
|
||||
|
||||
```js
|
||||
getWeather("Los Angeles").then((weather) => {
|
||||
console.log(weather); // Sunny, probably
|
||||
});
|
||||
```
|
||||
|
||||
Outlining this one again, because it's very common, is to attempt to use the value of a promise, but not resolving it:
|
||||
|
||||
```js
|
||||
// Incorrect code, don't copy!
|
||||
const weather = getWeather("Los Angeles");
|
||||
console.log(weather); // Promise {<pending>}
|
||||
```
|
||||
|
||||
## Real World Example
|
||||
|
||||
Here is a real function that gets character information from the Rick and Morty API.
|
||||
You can try it in your browser if you want to test it out.
|
||||
|
||||
```js
|
||||
function getCharacters() {
|
||||
return fetch(`https://rickandmortyapi.com/api/character`)
|
||||
.then((response) => response.json())
|
||||
.then((response) => response.results);
|
||||
}
|
||||
|
||||
getCharacters().then((characters) => {
|
||||
console.log(characters); // (20) [{...}, {...}, {...}]
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,72 @@
|
||||
---
|
||||
authors:
|
||||
- "Xetera#0001"
|
||||
created_at: "2019/07/26"
|
||||
title: Simplifying Promises
|
||||
---
|
||||
|
||||
The first naive attempt, using new Promise for something that already returns a promise.
|
||||
|
||||
```js
|
||||
function doAsync(number) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
doDatabase().then(function (dbResult) {
|
||||
otherDbFunction(dbResult).then(function (secondResult) {
|
||||
resolve(secondResult + 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Turns out you don't need new Promise if you're working with a function that
|
||||
already returns a promise, you can just return the original thing.
|
||||
|
||||
```js
|
||||
function doAsync(number) {
|
||||
return doDatabase().then(function (dbResult) {
|
||||
otherDbFunction(dbResult).then(function (secondResult) {
|
||||
return secondResult + 10;
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
You also don't have to nest `.then` functions, the whole point of promises
|
||||
is that they allow you to chain them sequentially.
|
||||
|
||||
```js
|
||||
function doAsync(number) {
|
||||
return doDatabase()
|
||||
.then(function (dbResult) {
|
||||
return otherDbFunction(dbResult);
|
||||
})
|
||||
.then(function (secondResult) {
|
||||
return secondResult + 10;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
you also don't have to create a new function just to pass in one
|
||||
variable, you can pass in the entire function itself to the then block
|
||||
|
||||
```js
|
||||
function doAsync(number) {
|
||||
return doDatabase()
|
||||
.then(otherDbFunction)
|
||||
.then(function (secondResult) {
|
||||
return secondResult + 10;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
And you don't need those returns if you just have ES6 arrow functions
|
||||
|
||||
```js
|
||||
const doAsync = (number) =>
|
||||
doDatabase()
|
||||
.then(otherDbFunction)
|
||||
.then((secondResult) => secondResult + 10);
|
||||
```
|
||||
|
||||
Wow, that last one looks a lot cleaner to me than the first. Keeping that in mind, maybe we could be making some of our other functions cleaner as well
|
||||
Reference in New Issue
Block a user