This posting mainly about three asynchoronous style in javascript and the usage of them
we will get through the inefficiency and inconvenience of chained callback and make the code better with other asynchronous solution(Promise and async) in jsavascript
it could not be the one of the asynchronous style as it is too commonly used in any coding style but for the comparison with Promise, I regard it as a "style"
let us get to the callback with a simple example
class User {
[1] getUserName(id, password, onSuccess, onError) {
[2] if (id === "user_id" && password === "user_password") {
[3] return onSuccess("heechul")
} else {
[4] onError(new Error("error in getUserName"))
}
}
[5] getUserLevel(name, onSuccess, onError) {
[6] if (name === "heechul") {
[7] onSuccess("admin")
} else {
[8] onError(new Error("error in getUserLevel"))
}
}
}
the User class has [1]getUserName method with 4 parameter all of which can be any type in javascript. [2]if idand password all satisfied to the condition, [3]it return the result of callback fucntion onSuccess [4]if not, it throw an error defined.
moving on to the another method [5]getUserLevel which has 3 different parameter(can be any type in js), it also call the potential [6]callback function onSuccess otherwise throw an error via another callback function onError, all of which are going to throw TypeError once those are not a function type.
now the the class is defined
why not we just call and check the outcome?
const user = new User() [1]
user.getUserLevel(
[2] user.getUserName(
"user_id",
"user_password",
[3] name => {
return name
},
[4] error => {
console.log(error)
}
),
[5] (level) => {
console.log(`the required user level is ${level}`)
},
[6] (error) => {
console.log(error)
}
)
firstly, we make instance of the class defined at [1].
then [2]get the user name via getUserName function ascychoronously ans pass it to the main function. at the point the [3]getUserName get the result what it is supposed to pass to the main function as a parameter, it(getUserName) have to return the result in order to avoid passing "undefined" to the getUserLevel
lastly, we get the result at the console
> the required user level is admin
However, if the codes become more complex and when you are in cooperation that your code have to be read by your coworker, the code messed with chained callback would be a nightmare to everyone including you living in future.
now we get to the Promise which could be a solution for complex chanined callback.
before you go, let us look into the concepts of Promise
Promise object Promise that "Producer" createPromise made. when it comes to return the result, it own the result being inside the Promise object transforming it's states to "fullfilled"Promise object transforming it's states to "rejected"here all with the code refactored with Promise
class User {
getUserName(id, password){
[1] return new Promise((resolve, reject) => {
if (id === "login_id" && password === "password") {
[2] resolve("heechul")
} else {
[3] reject(new Error("error in getUserName"))
}
})
}
getUserLevel(name) {
[4] return new Promise((resolve, reject) => {
if (name === "heechul") {
[5] resolve("admin")
} else {
[6] reject(new Error("error in getUserLevel"))
}
})
}
}
[7] const user = new User()
[8] user.getUserName("login_i", "password")
[9] .then(name => user.getUserLevel(name))
[10] .catch(error => return "userLevel_1")
[11] .then(level => console.log(level))
[12] .catch(error => console.log(error))
Promsie javascript equipted class has pre-set constructor, resolve for success and reject for error
once you pass parameter to the
Promiseconstructor, it process code as soon as it receive them. so you want to aware of it in order to decide the moment you resolve the result.
[1] if you want to use Promise, use the main function as a wrapper(for receiving parameter) and return the Promise for core logic.
[2] put the value you want to return in the resolve
[3] finally put the unwanted value in the reject
[7] assign the instance of User and call the getUserName passing two pre-set parameter
[8] then the getUserName return the [2]resolve with the value inside which [9]right position to the first parameter of the unnamed function in then
the result
getUserNameresolved isPromiseobject with the "fullfilled" state enabling for the result ofgetUserNameuse.thenwhich means if the statePromiseis not "fullfuilled", Promise object cannot use.then
[10] now you catch the error with .catch method in Promise with "rejected". so if you want to handle an error, use .catch at the right position. it is possible not throw an error but replacing the error into other value in order to complete the whole scope. In this case, if the error raised, the return value replaced to "userLevel_1".
[12] finally we handle an error at the last of the Promise chain
you may find the code is processed synchronously with Promise so that it looks much easier to understand.