mirror of
https://github.com/xfarrow/javascript-tutorials.git
synced 2025-06-05 21:59:24 +02:00
renaming folder
This commit is contained in:
55
asynchronous_programming/0_callbacks.js
Normal file
55
asynchronous_programming/0_callbacks.js
Normal file
@ -0,0 +1,55 @@
|
||||
// https://javascript.info/callbacks
|
||||
|
||||
entryPoint()
|
||||
|
||||
function entryPoint () {
|
||||
execute_action('something', function (error, time_of_completion) {
|
||||
if (error) {
|
||||
console.log('Something happened')
|
||||
} else {
|
||||
console.log('Time of completion: ' + new Date(time_of_completion).toDateString())
|
||||
}
|
||||
})
|
||||
console.log("I don't need execute_action's value")
|
||||
}
|
||||
|
||||
function execute_action (param, callback) {
|
||||
if (param == 'something') {
|
||||
console.log('Executing action: ' + param)
|
||||
callback(null, Date.now())
|
||||
} else {
|
||||
// We can call callback with one argument even if
|
||||
// the signature states two parameters.
|
||||
callback(new Error('Invalid parameter'))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is useful when, for example, execute_action performs slow operations
|
||||
(such as I/O, HTTP requests etc) and we need its result to continue a
|
||||
specific operation (in this case the date of completion), without blocking
|
||||
other portions of code that do not need such value, in this case
|
||||
"console.log("I don't need execute_action's value");"
|
||||
|
||||
But please note that this is only an example. In this code all
|
||||
operations will be executed synchronously, but this allows us
|
||||
to understand the basics of this mechanism.
|
||||
|
||||
Output:
|
||||
Executing action: something
|
||||
Time of completion: Sun Jun 30 2024
|
||||
I don't need execute_action's value
|
||||
|
||||
Callbacks are usually meant for asynchronous programming. When
|
||||
we meet a function that accepts a callback, it is likely an
|
||||
asynchronous function, such as
|
||||
setTimeout(callback, delay).
|
||||
|
||||
Callbacks are not asynchronous by nature, but can be used
|
||||
for asynchronous purposes.
|
||||
|
||||
The problem is that this makes the code harder to read
|
||||
so modern JS is written using Promises and async/await
|
||||
constructs.
|
||||
|
||||
*/
|
61
asynchronous_programming/1_promises.js
Normal file
61
asynchronous_programming/1_promises.js
Normal file
@ -0,0 +1,61 @@
|
||||
// https://javascript.info/promise-basics
|
||||
|
||||
/*
|
||||
The function passed to Promise is called "executor"
|
||||
and gets executed synchronously and immediately after the Promise is created.
|
||||
When the Promise ends, the callback function should
|
||||
either call the "resolve" or "reject" callbacks:
|
||||
resolve(value) — if the job is finished successfully, with result value.
|
||||
reject(error) — if an error has occurred, error is the error object.
|
||||
|
||||
A Promise can be in one of these three states:
|
||||
- Pending (the operation is being processed)
|
||||
- Fullfilled (the operation has completed successfully, resolve has been called)
|
||||
- Rejected (the operation has not completed successfully, reject has been called)
|
||||
|
||||
A promise represents the completion of a (likely) asynchronous function. It is an object
|
||||
that might return a value in the future. It accomplishes the same basic goal as a
|
||||
callback function, but with many additional features and a more readable syntax.
|
||||
*/
|
||||
const promise = new Promise(function (resolve, reject) {
|
||||
setTimeout(() => resolve('done'), 5000)
|
||||
})
|
||||
|
||||
/*
|
||||
The first argument of .then is a function that runs when the promise is resolved and receives the result.
|
||||
The second argument of .then is a function that runs when the promise is rejected and receives the error.
|
||||
*/
|
||||
promise.then(
|
||||
result => console.log('The operation was successful. It returned ' + result),
|
||||
error => console.log('The operation was not successful: ' + error)
|
||||
)
|
||||
|
||||
/*
|
||||
Or we can pass only one argument if we're interested only in a positive result
|
||||
*/
|
||||
promise.then(
|
||||
result => console.log('The operation was successful. It returned ' + result)
|
||||
)
|
||||
|
||||
/*
|
||||
Or we can pass only one argument to the method "catch" if we're interested
|
||||
in negative results only.
|
||||
|
||||
promise.catch internally just calls promise.then(null, f)
|
||||
*/
|
||||
promise.catch(
|
||||
error => console.log(error)
|
||||
)
|
||||
|
||||
/*
|
||||
finally gets always called
|
||||
*/
|
||||
promise.finally(
|
||||
() => console.log('The execution has terminated. Bye')
|
||||
)
|
||||
|
||||
/*
|
||||
This line is used to demonstrate that the code within "then, catch, etc."
|
||||
is in the event loop, as this is the first line getting executed.
|
||||
*/
|
||||
console.log('Last line')
|
48
asynchronous_programming/2_promise-chaining.js
Normal file
48
asynchronous_programming/2_promise-chaining.js
Normal file
@ -0,0 +1,48 @@
|
||||
// https://javascript.info/promise-chaining
|
||||
|
||||
// .then() returns a new Promise when you do "return",
|
||||
// internally calling resolve().
|
||||
|
||||
new Promise(function (resolve, reject) {
|
||||
setTimeout(() => resolve(1), 1)
|
||||
}).then(function (result) {
|
||||
console.log(result)
|
||||
return result * 2
|
||||
}).then(function (result) {
|
||||
console.log(result)
|
||||
return result * 2
|
||||
}).then(function (result) {
|
||||
console.log(result)
|
||||
return result * 2
|
||||
})
|
||||
|
||||
/*
|
||||
It will print
|
||||
1
|
||||
2
|
||||
4
|
||||
*/
|
||||
|
||||
/*
|
||||
It means that "then" is internally implemented roughly as follows:
|
||||
|
||||
function then(f){
|
||||
return new Promise(function(resolve, reject) {
|
||||
resolve(f());
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
// Another example:
|
||||
|
||||
fetch('http://www.fsf.org')
|
||||
// .then below runs when the remote server responds
|
||||
.then(function (response) {
|
||||
// response.text() returns a new promise that resolves with the full response text
|
||||
// when it loads
|
||||
return response.text()
|
||||
})
|
||||
.then(function (text) {
|
||||
// ...and here's the content of the remote file
|
||||
console.log(text)
|
||||
})
|
60
asynchronous_programming/3_async-await.js
Normal file
60
asynchronous_programming/3_async-await.js
Normal file
@ -0,0 +1,60 @@
|
||||
// https://javascript.info/async-await
|
||||
|
||||
// An async function always returns a promise. Other values are wrapped in a resolved promise automatically.
|
||||
// Async and await are merely syntactic sugar in order to make Promise usage easier
|
||||
|
||||
async function f1 () {
|
||||
return 1
|
||||
}
|
||||
|
||||
f1().then(console.log) // 1
|
||||
|
||||
// The keyword await makes JavaScript wait until that promise settles and returns its result.
|
||||
// It can be used in async functions only.
|
||||
// Let’s emphasize: await literally suspends the function execution until the promise settles,
|
||||
// and then resumes it with the promise result.
|
||||
async function f2 () {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => resolve('done!'), 1000)
|
||||
})
|
||||
const result = await promise // wait until the promise resolves (*)
|
||||
console.log(result) // "done!"
|
||||
}
|
||||
f2()
|
||||
|
||||
// The code in the same function after "await"
|
||||
// is to be intended in the "then()" of the primise. This means
|
||||
// that after await (but before the completion of the Promise),
|
||||
// the flow of execution goes out that code block. For example
|
||||
// consider the following example:
|
||||
async function exampleAsyncFunction () {
|
||||
console.log('Before await')
|
||||
await new Promise(function (resolve, reject) {
|
||||
setTimeout(() => resolve('done'), 500)
|
||||
}) // Pauses execution here until the promise resolves.
|
||||
console.log('After await')
|
||||
}
|
||||
console.log('Start')
|
||||
exampleAsyncFunction()
|
||||
console.log('End')
|
||||
|
||||
// The result will be:
|
||||
// Start, Before Await, End, After await
|
||||
// "End" comes before "After Await" because the
|
||||
// flow of execution goes to the caller
|
||||
// when await is invoked.
|
||||
|
||||
// Questions
|
||||
//
|
||||
// Why await only works in async function in javascript?
|
||||
// https://stackoverflow.com/questions/49640647/why-await-only-works-in-async-function-in-javascript
|
||||
//
|
||||
// Why using async-await
|
||||
// https://stackoverflow.com/questions/42624647/why-use-async-when-i-have-to-use-await
|
||||
//
|
||||
// Be mindful: it is not possible to create an async function from scratch (such as
|
||||
// setInterval o fetch)
|
||||
// https://stackoverflow.com/questions/61857274/how-to-create-custom-asynchronous-function-in-javascript
|
||||
//
|
||||
// Another question that may be interesting
|
||||
// https://stackoverflow.com/questions/42624647/why-use-async-when-i-have-to-use-await
|
52
asynchronous_programming/README.md
Normal file
52
asynchronous_programming/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
# Asynchronous JavaScript
|
||||
|
||||
JavaScript is single-threaded but it can still take advantage of asynchronous
|
||||
programming.
|
||||
|
||||
When we say JavaScript is single-threaded, we mean that we cannot write
|
||||
multithread/concurrent code without using JavaScript APIs. In fact,
|
||||
despite for us it appears single-threaded, it takes advantage of the
|
||||
`libuv` library, allowing the engine to be effectively multithread.
|
||||
|
||||
Another way to put it is that we have one and only one Call Stack.
|
||||
|
||||
In order to do that, JavaScript uses
|
||||
* The libuv APIs which allow multithreading
|
||||
* The Event Loop Queue
|
||||
|
||||
## Explaination
|
||||
JavaScript provides a set of APIs, including `setTimeout` and `fetch`, which
|
||||
are offloaded to the libuv library when called. The libuv library handles the
|
||||
underlying operations, such as timer management and HTTP requests, respectively.
|
||||
|
||||
While `libuv` performs these operations, our JavaScript code continues its
|
||||
execution, without being blocked. That's why we said that the engine is
|
||||
multithreaded.
|
||||
|
||||
Both `setTimeout` and `fetch` have associated functions, known as callbacks, that
|
||||
are executed once the operation has completed.
|
||||
Since the engine cannot directly push these callback functions onto the call stack
|
||||
without disrupting the current flow of execution, it instead places them in a
|
||||
queue called the "Event Loop Queue". When the call stack is empty, the engine
|
||||
checks the queue and, if there are any pending callbacks, proceeds to execute them.
|
||||
|
||||
**Example**
|
||||
|
||||
```javascript
|
||||
setTimeout(() => console.log('I will go in the event loop queue first'), 1000);
|
||||
console.log('I am in the stack');
|
||||
```
|
||||
|
||||
What is happening here? `setTimeout` is a JavaScript API which will be taken care
|
||||
of by the `libuv` library which will be responsible for checking when 1000ms have passed.
|
||||
**Concurrently**, the engine executes
|
||||
`console.log('I am in the stack');`.
|
||||
When 1000ms have elapsed, the callback function associated with the timer (console.log)
|
||||
gets enqueued in the Queue.
|
||||
Since there is nothing to do in the stack, the callback pushes the callback onto the
|
||||
stack and executes it.
|
||||
|
||||
## Useful resources
|
||||
* https://www.youtube.com/watch?v=lqLSNG_79lI
|
||||
* https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif
|
||||
* https://www.youtube.com/watch?v=eiC58R16hb8
|
31
asynchronous_programming/sincrono_vs_asincrono.txt
Normal file
31
asynchronous_programming/sincrono_vs_asincrono.txt
Normal file
@ -0,0 +1,31 @@
|
||||
Link utili:
|
||||
https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-is-the-difference
|
||||
https://stackoverflow.com/questions/7131991/asynchronous-and-synchronous-terms
|
||||
|
||||
La parola "sincrono" in contesto informatico vuol dire "sincronizzato", ovvero
|
||||
il chiamante deve aspettare la risposta del chiamato, mentre
|
||||
"async" vuol dire "non sincronizzato".
|
||||
Ciò vuol dire (non)/sincronizzato con altre porzioni di codice.
|
||||
La definizione da dizionario invece differisce.
|
||||
Per Treccani: "Sincrono: Che avviene nello stesso momento",
|
||||
mentre sappiamo che un'operazione sincrona rispetto ad un'altra
|
||||
non avviene allo stesso tempo.
|
||||
In informatica dire "un metodo è (a)sincrono" deve
|
||||
sempre accompagnate da "rispetto a chi" è (a)sincrono.
|
||||
|
||||
Possiamo anche pensarla così: (https://stackoverflow.com/a/32052611/18371893)
|
||||
|
||||
In a nutshell, synchronization refers to two or more processes' start and end points, NOT their executions.
|
||||
In this example, Process A's endpoint is synchronized with Process B's start point:
|
||||
|
||||
SYNCHRONOUS
|
||||
|--------A--------|
|
||||
|--------B--------|
|
||||
|
||||
Asynchronous processes, on the other hand, do not have their start and endpoints synchronized:
|
||||
|
||||
ASYNCHRONOUS
|
||||
|--------A--------|
|
||||
|--------B--------|
|
||||
|
||||
Where Process A overlaps Process B, they're running concurrently or synchronously (dictionary definition), hence the confusion.
|
Reference in New Issue
Block a user