Cara menggunakan callback function javascript freecodecamp

Panduan Referensi APIAWS SDK for JavaScript V3 menjelaskan secara rinci semua operasi API untukAWS SDK for JavaScript versi 3 (V3).

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Setiap metode objek layanan dapat menerima fungsi callback anonim sebagai parameter terakhir. Tanda tangan dari fungsi callback ini adalah sebagai berikut.

function(error, data) {
    // callback handling code
};

Fungsi callback ini mengeksekusi ketika baik respon sukses atau data kesalahan kembali. Jika metode panggilan berhasil, isi respon yang tersedia untuk fungsi callback didataparameter. Jika panggilan tidak berhasil, rincian tentang kegagalan disediakan dierrorparameter.

Biasanya kode di dalam fungsi callback tes untuk kesalahan, yang diproses jika salah satu dikembalikan. Jika kesalahan tidak dikembalikan, kode kemudian mengambil data dalam respon daridataparameter. Bentuk dasar dari fungsi callback terlihat seperti contoh ini.

function(error, data) {
    if (error) {
        // error handling code
        console.log(error);
    } else {
        // data handling code
        console.log(data);
    }
};

Pada contoh sebelumnya, rincian kesalahan atau data yang dikembalikan dicatat ke konsol. Berikut adalah contoh yang menunjukkan fungsi callback dilewatkan sebagai bagian dari memanggil metode pada objek layanan.

Back-end developers run into challenges all the time while building applications or testing code. As a developer who is fairly new and getting acquainted with those challenges, I have never run into a challenge or inconvenience more frequently — or more memorable — than with callback functions.

I am not going to delve too deeply into the details of callback and its pros and cons or alternatives like promises and async/await. For a more vivid explanation, you can check out this article which explains them thoroughly.

Callback Hell

Callbacks are a useful feature of JavaScript’s that enables it make asynchronous calls. They are functions that are usually passed on as a second parameter to another function that is fetching data or doing an I/O operation that takes time to complete.

For example, try making an API call using the request module or connecting to a MongoDB database. But what if both calls depend on each other? What if the data you’re fetching is the MongoDB URL that you need to connect to?

You’d have to nest these calls inside each other:

request.get(url, function(error, response, mongoUrl) {  if(error) throw new Error("Error while fetching fetching data");  MongoClient.connect(mongoUrl, function(error, client) {    if(error) throw new Error("MongoDB connection error");    console.log("Connected successfully to server");    
const db = client.db("dbName");
// Do some application logic
client.close();
});});

Okay…so where’s the problem? Well, for one thing, the readability of the code suffers from this technique.

It may seem OK at first when the codebase is small. But this doesn’t scale well, especially if you go more layers deeper into the nested callbacks.

You will end up with a lot of closing brackets and curly braces that will confuse you and other developers no matter how neatly formatted your code is. There is a website called callbackhell that addresses this specific issue.

I hear some of you, including my naïve past self, telling me wrap it in an async function then awaitthe callback function. This just doesn’t work.

If there is any code block after the the function that uses callbacks, that code block will execute and will NOT wait for the callback.

Here’s that mistake that I did before:

var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};

Some more experienced devs might say “Just use a different library that uses promises to do the same thing, like axios, or just use fetch”. Sure I can in that scenario, but that’s just running away from the problem.

Besides, this is just an example. Sometimes you can be locked into using a library that doesn’t support promises with no alternatives. Like using software development kits (SDKs) to communicate with platforms like Amazon Web Services (AWS), Twitter, or Facebook.

Sometimes, even using a callback to do a very simple call with a quick I/O or CRUD operation is fine, and no other logic depends on its results. But you might be constrained by the runtime environment like in a Lambda function which would kill all process once the main thread finishes, regardless of any asynchronous calls that did not complete.

Solution 1 (easy): Use Node’s “util” module

The solution is surprisingly simple. Even if you’re a little uncomfortable with the idea of promises in JavaScript, you will love how you can solve this issue using them.

As pointed out by Erop and Robin in the comments, Nodejs version 8 and above now support turning callback functions into promises using the built-in util module.

const request = require('request');const util = require('util');
const url = "https://api.chucknorris.io/jokes/random";
// Use the util to promisify the request method
const getChuckNorrisFact = util.promisify(request);
// Use the new method to call the API in a modern then/catch patterngetChuckNorrisFact(url).then(data => { let content = JSON.parse(data.body); console.log('Joke: ', content.value);}).catch(err => console.log('error: ', err))

The above code solves the problem neatly using the method available from nodejs core library.

All you have to do is use the callback function as an argument to util.promisify, and store it an a variable. In my case, that’s getChuckNorrisFact.
Then you use that variable as a function that you can use like a promise with the .then() and the .catch() methods.

Solution 2 (involved): Turn the Callback into a Promise

Sometimes, using the request and util libraries is just not possible, whether it’s because of a legacy environment/code base or doing the requests from the client-side browser, you have to wrap a promise around your callback function.

Let’s take the Chuck Norris example above, and turn that into a promise.

var request = require('request');
let url = "https://api.chucknorris.io/jokes/random";
// A function that returns a promise to resolve into the data //fetched from the API or an error
let getChuckNorrisFact = (url) => {
return new Promise(
(resolve, reject) => {

request.get(url, function(error, response, data){
if (error) reject(error);
let content = JSON.parse(data);
let fact = content.value;
resolve(fact);
})
}
);

};
getChuckNorrisFact(url).then(
fact => console.log(fact) // actually outputs a string
).catch(
error => console.(error)
);

works like magic

In the code above, I put the callback-based request function inside a Promise wrapper Promise( (resolve, reject) => { //callback function}). This wrapper allows us to call the getChuckNorrisFact function like a promise with the

var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
0 and
var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
1 methods. When the
var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
2 is called, it executes the request to the API and waits for either a
var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
3 or a
var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
4 statement to execute. In the callback function, you simply pass the retrieved data into the resolve or reject methods.

Once the data (in this case, an awesome Chuck Norris fact) is fetched and passed to the resolver, the getChuckNorrisFact executes the

var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
6 method. This will return the result that you can use inside a function inside the
var request = require('request');// WRONGasync function(){  let joke;
let url = "https://api.chucknorris.io/jokes/random"
await request.get(url, function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};// Wrongasync function(){ let joke;
let url = "https://api.chucknorris.io/jokes/random"
request.get(url, await function(error, response, data) { if(error) throw new Error("Error while fetching fetching data"); let content = JSON.parse(data);
joke = content.value;
}); console.log(joke); // undefined};
7 to do your desired logic — in this case displaying it to the console.