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 id
and 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
Promise
constructor, 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
getUserName
resolved isPromise
object with the "fullfilled" state enabling for the result ofgetUserName
use.then
which means if the statePromise
is 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.