# Asynchronous Javascript
- Thread = A single process to do all tasks. But one task at one time.
- Javascript is synchronous, blocking, single threaded called
main thread
- eg: Use
alert()
to block code.
- eg: Use
- Webworkers are used to create a
worker thread
- But it has no access to DOM
- Promises use
worker thread
and after processing returns result tomain thread
. - Callbacks functions are a bit old now. But still used. eg:
addEventListener(event, callback)
- Some callback are synchronous. Ex.
Array.prototype.forEach(arr, callback)
- Some callback are synchronous. Ex.
- Event Queue - Async tasks are added to the event queue which runs after
main thread
has finished with tasks ie empty stack.
# Timeout & Intervals
# setTimeout/setInterval
setTimeout(callback, milliseconds, parameters); // 1000 = 1s
setTimeout(callback, 0); // Runs after main thread is empty. (not immediately)
clearTimeout(name);
setInterval(callback, milliseconds, parameters);
clearInterval(name);
// Recursive callback in setTimeout() === setInterval()
// Difference = Time to run inside code is counted for setInterval() but not for setTimeout()
// setTimeout() executes after 200ms only irrespective of time taken to run code
function foo() {
// code
setTimeout(foo, 200);
}
setInterval(foo, 200);
# requestAnimationFrame
- Better than
setTimeout/setInterval
- Use to call a function repeatedly & efficiently especially for animations
- Frame Per Second (FPS) - higher is better
- Most screens has Refresh rate of 60Hz which can give atmost 60FPS
- MDN Example (opens new window)
- Cons
- Can't choose custom frame rate.
# Promises
Promises is the new way for Asynchronous code
- Promise - An object with info on success/failure.
- Promises vs Callbacks
- No Callback Hell - Promises return an object to which we can attach a callback using
then()
(But nested promises MAY lead to HELL too) - No try/catch repeation - Just 1
catch()
for any errortry...catch
- not allowed in async code.then()/catch()/finally()
is the async equivalent totry/catch/finally
in syncthrow new Error("An error occurred")
- allowed.
- No Callback Hell - Promises return an object to which we can attach a callback using
resolve(data)/reject(data)
- takes 0 or 1 argstate:
property- possible state =
pending/fulfilled/rejected
pending
- working- Resolved - work done promise object is returned;
fulfilled
- Fromresolve(data)
- usethen(data)
rejected
- Fromreject(data)
- usecatch(data)
- possible state =
result:
propertyundefined
- if state ispending
data
passed byresolve(data) / reject(data)
- Static methods
Promise.resolve().then()
Promise.reject().then()
# Promise Constructor
let parameterA = "parameterAValue";
let pro = new Promise((resolve, reject) => {
console.log(parameterA);
setTimeout(() => resolve(), 500);
// setTimeout(()=> reject(), 500 );
}, parameterA);
pro
.then(() => {
console.log("then()");
})
.catch(() => {
console.log("catch()");
})
// no args but passes value/error
.finally(() => {
console.log("-----");
});
# Multiple chaining
- We can chain multiple
then()
. - Ex.
Fetch
api returns a promise object.- Fetch promises do not fail on
404 or 500
errors (Better to use Axios)
- Fetch promises do not fail on
// Ex
let promise = fetch("coffee.jpg");
// Ex
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => {
console.log("then_1");
return response.json();
})
.then((json) => {
console.log("then_2");
console.log(json);
})
.catch((err) => {
console.log("catch() - " + err.message);
})
.finally(() => {
console.log("-------------");
});
# Promise.all
- All below are static methods.
Promise.all
- All must fulfill else block is rejectedPromise.allSettled
- returnsstate/result
property irrespective of success/failure of any promise.Promise.resolve/reject
- not needed due to async/await
let p1 = fetch("url1");
let p2 = fetch("url2");
let p3 = fetch("url3");
Promise.all([p1, p2, p3]).then([p1result, p2result, p3result]);
- All promises are started at same time ie parallel.
console.log(new Date().getSeconds()); // 20s
let p1 = new Promise((resolve) => setTimeout(() => resolve(1), 4000));
let p1 = new Promise((resolve) => setTimeout(() => resolve(2), 2000));
Promise.all([p1, p2]).then((a) => {
console.log(a); // [1, 2]
console.log(new Date().getSeconds()); // 24s
});
# Async/Await
- syntactic sugar to use Promises
async
function will always return a promise object.await
only works insideasync()
functionawait
is always written before a promise object.try, catch, finally
can be used inasync
function
# async/await
- It does not use
then()
method
// Ex 1:
async function foo() {
return "hello";
}
console.log(foo()); // Promise {<fulfilled>: "hello"}
// Ex 2:
async function hello() {
let msg = await fetch("url"); // line is paused by javascript till it is resolved & returns a promise object.
console.log(msg);
}
hello();
# async/await - then()
- It uses both
await
&then()
method by returning a promise object.
async function hello() {
let response = await fetch("url");
if (response.ok) {
return response;
} else {
throw new Error("Error in fetch");
}
}
// INVOKE
hello()
.then((value) => {
console.log(value);
})
.catch((err) => {
console.log(err);
});
# async/await - Promise.all()
// fetch one url
async function myFetchOne(url) {
let response = await fetch(url);
if (response.ok) {
return response;
} else {
throw new Error("A new Error in Promise.all()");
}
}
// fetch all urls
async function myFetchAll() {
let aPro = await myFetchOne("url");
let bPro = await myFetchOne("url");
let cPro = await myFetchOne("url");
let response = await Promise.all([aPro, bPro, cPro]);
console.log("All Fetch are successful");
console.log(response[0]);
console.log(response[1]);
console.log(response[2]);
}
myFetchAll().catch((err) => console.log(err));
# Downside (with solution)
- In above example we have 3
myFetchOne("url")
- The
bPro
&cPro
will not start unless 1staPro
is completed/resolved. - To solve this issue just assign the
myFetchOne("url")
to variables. - This will start all 3 promises simultaneously. They might take any time to finish, but they are not blocked by each other.
- In short - Wait for results but start all promises at the same time.
async function myFetchAll() {
let aPro = myFetchOne("url");
let bPro = myFetchOne("url");
let cPro = myFetchOne("url");
await aPro;
await bPro;
await cPro;
// code.....
}
# Fetch Api
let promise = fetch(url, options);
let promise = fetch(url); // GET only
// ex
let res = fetch(url);
res.ok;
res.status; // if not ok ie error
res.headers;
// get data
res.text();
res.json();
res.formData();
res.blob(); // Binary data with type
res.arrayBuffer(); // low level representation of Binary data
# Headers
- Not allowed Headers (controlled by browser) - https://fetch.spec.whatwg.org/#forbidden-header-name (opens new window)
// POST
let options = {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: "", // Text/Json/FormData/Blob
};
let res = fetch(url, options);
# Upload/Download progress
- Only download progress can be known. (Upload progress is not available)
response.body
- a ReadableStream object- Data is received in samll chunks
# Abort
let controller = new AbortController();
fetch(url, {
signal: controller.signal,
})
.then()
.catch((err) => {
if (err.name === "AbortError") alert("Request cancelled.");
});
controller.abort(); // cancel fetch request.
# CORS
Cross Origin Resource Sharing
- Origin - Combination of
domain + port + protocol
- Fetch from
myDomain.com
can send request tootherDomain.com
myDomain.com
- BrowserotherDomain.com
- Server
Cross Request types :
- Safe
- All others are Unsafe
- Browser always adds this header to request
Origin: 'http://myDomain.com'
(without path)
# Safe Request
- Methods allowed -
GET / POST / HEAD
- Headers allowed
Accept
Accept-Language
Content-Language
Content-Type
- Only this are allowedapplication/x-www-form-urlencoded, multipart/form-data or text/plain
- How to use ?
- Use
<form>
with<iframe>
as target (Avoid) - Use
<script src="otherDomain.com/home?foo=bar&doo=zoo">
- Use
# Unsafe Request
- Needs confirmation by
otherDomain.com
server - Confirmation is done using headers.
Access-Control-Allow-Origin:
- value asmyDomain.com
or*
- For 1 request browser sends 2 request
preflight
- To check if server accepts request frommyDomain.com
actual request
# Credentials
Credentials - Cookie or Authentication
- Server should respond with header
Access-Control-Allow-Credentials: true
// Browser cookies from "otherDomain.com" are attached in fetch request by "myDomain.com"
fetch("https://otherDomain.com", {
credentials: "include",
});
# WebSocket
Use socketio/socket.io (opens new window)
http/1.1
- Synchronoushttp/2
- ASynchronous but needs request to initiate.websocket
- Fully ASynchronous & Persistent connection - Client/server can connect to each other anytimeGood for real time communication games, chats, etc
Protocol -
ws://mydomain.com
&wss://mydomain.com
(secured)4 Events -
open, close, error, message
let ws = new WebSocket("wss://mydomain.com");
// Events
ws.onopen;
ws.onclose;
ws.onmessage;
ws.onerror;
// send data
ws.send(data);
# Cookies
document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
- Headers
Set-Cookie
- Created by serverCookie
- Created by browser
- key-value pairs Limit - approx 20 per domain
document.cookie; // a=foo;b=bar;
document.cookie = "a=foo; b=bar;"; // Create - new one is created. Old one is not replaced.
// Encoding
let e = encodeURIComponent(text);
// Options
("foo=bar;"); // key-value
("path=/;"); // url path (if path=/admin then cookie is valid only on /admin/* path & no other paths)
("domain=mydomain.com"); // allows all subdomains too
("expires=Tue, 19 Jan 2038 03:14:07 GMT"); // session cookies - use any one expires or max-age
("max-age=3600;"); // 3600 seconds = 1hr
("secure;"); // https
("samesite=strict;"); // xsrf protection
("httpOnly;"); // set by server to not allow javascript any access to cookie
#
← Javascript DOM →