Photo by Adi Goldstein on Unsplash
Ảnh của Adi Goldstein trên Unsplash

Lời nói đầu

Callbacks internalizing rất quan trọng. Đó là một khái niệm trong một số ngôn ngữ lập trình bao gồm c, c #, đỏ và rebol, lua, python và javascript.

Tuy nhiên, trong javascript, nó là nền tảng như ngôn ngữ.

Lệnh Callback là một hàm được truyền dưới dạng đối số của hàm và được gọi tại một số điểm trong hàm. Các lệnh Callback được sử dụng để đóng gói logic sẽ được thực thi trong hàm gọi thường chứa logic khác có thể chung với logic lập trình của chúng ta.

Rõ ràng, có sự nhầm lẫn này đi kèm với việc học một ngôn ngữ lập trình mới. Những người mới bắt đầu sẽ thường gặp phải những lập trình viên có kinh nghiệm đưa ra những điều nên làm và không nên làm, chỉ trích những người mới làm quen với những lĩnh vực mà họ nên tránh. Một trong những khái niệm mà chúng tôi được khuyên nên sử dụng một cách tiết kiệm là Callback.

Bạn có thể đã gặp phải địa ngục Callback. Nơi mà chúng ta được cho là phải cảnh giác với Callbacks nhưng tin tôi đi, bạn cần biết các lệnh Callbacks trước khi có thể biết cách tránh phần 'quái quỷ' của nó. Sử dụng các tính năng JavaScript hiện đại như async / await là một số giải pháp. Tuy nhiên, mô-đun hóa mã có thể cho phép chúng ta thành thạo trong việc lập trình với các lệnh Callback một cách hiệu quả. Tuy nhiên, để trở thành một kỹ sư JavaScript thành công, người ta phải thông thạo các khái niệm lập trình cốt lõi của nó, một trong số đó là Callback.

Callback có thể làm gì?

Hiểu được callback là gì là rất quan trọng trong JavaScript. Các lệnh callback cung cấp cho chúng tôi khả năng cho phép người dùng khả năng đóng gói logic nghiệp vụ cụ thể cho yêu cầu của họ để trở thành một phần của quá trình thực thi mã. Ví dụ, hầu hết các phương thức mảng (ánh xạ, bộ lọc và giảm) sử dụng các hàm callback. Trong đoạn mã dưới đây, chúng ta đã truyền một hàm nhận x và lặp qua tất cả các giá trị trong một mảng và xuất ra một mảng khác. Chúng ta đã truyền hàm này (x = x * 2) được gọi nội bộ tại một số điểm trong hàm array.map.

const array = [1, 4, 9, 16];

// pass a function to map
const map = array.map(x => x * 2);

Rất nhiều hàm đối tượng cốt lõi của JavaScript sử dụng callback. Khi xử lý các đối tượng trên tài liệu web, hàm addEventListener của các phần tử html trong document trình duyệt sẽ callback để xử lý logic trang web của chúng tôi để thêm trình xử lý sự kiện vào các phần tử khác nhau mà chúng tôi có trên trang web của mình. Như chúng ta đã biết, chúng ta có thể thực hiện các hoạt động của mình trong vanilla JS. Nút gửi bên dưới thêm người nghe vào nút gửi để xem các sự kiện nhấp chuột. Chúng tôi đã chuyển hàm watchSubmit làm lệnh gọi lại của chúng tôi.

// Web api interface for adding event handlers

element.addEventListener(event, callback, useCapture)

//Vanilla JavaScript

function watchSubmit(){

const submit = document.getELementById('submit');
const targetElem =      document.getElementById("startupRegistered");
console.log(targetElem.value);
const targetElem2 =    document.getElementById("startupNotRegistered");
console.log(targetElem2.value);

}

submit.addEventListener("click", watchSubmit());

//jquery version

$('submit')
.html('Click me')
.on('click', watchSubmit());

Các lệnh callback được sử dụng để thực thi logic tùy chỉnh được chuyển đến một hàm trong đó hàm là chung theo một nghĩa nào đó và yêu cầu lệnh callback cung cấp quá trình xử lý duy nhất trong hàm đó tại thời điểm gọi.

Máy chủ web giả thuyết

Hãy xem một ví dụ khác về callback. Một máy chủ web giả định nhưng đây thực sự là ý tưởng đơn giản hóa về cách bạn có thể phát triển một máy chủ web. Hãy bắt đầu với bộ định tuyến và trình xử lý.

var router = {};

router.get = function (data, callback) {
callback(200, data);
}

router.notFound = function (data, callback) {
callback(404, { 'message': 'not found' })

}

var handler = {
"get": router.get,
"notFound": router.notFound

}

Chúng tôi cần một bộ định tuyến xử lý mặc định router.notFound trong trường hợp bạn đang cố gắng làm cho chúng tôi mệt mỏi. Tìm kiếm những gì không tồn tại. Bây giờ bên dưới là nơi chúng ta sẽ gọi hàm callback bên trong hàm serveRequest.

function serveRequest(req, res) {
var data = {
"query": req.query,
"body": req.body

};

var chosenhandler = handler[req.pathname] === undefined ?   
handler.notFound:handler[req.pathname];

chosenhandler(data, function (statusCode, payload) {

//Do some processing
res.query = req.query;
res.status = statusCode;

});
return res;
}

var req = {
"query": "firstname=thankgod",
"pathname": "get"
}

const res = serveRequest(req, {});

console.log(res);

Bây giờ nếu chúng ta gửi một yêu cầu đến bộ định tuyến của mình, đối tượng yêu cầu của chúng ta có một tên đường dẫn thay đổi cho chúng ta biết đường dẫn mà chúng ta muốn truy cập trong bộ định tuyến của mình. Khi chúng ta gọi một đường dẫn, trình xử lý chosenhandler  của bộ định tuyến sẽ định tuyến chúng ta đến đúng đường dẫn sẽ nhận lệnh callack để xử lý các yêu cầu của chúng ta.

Quản lý Giao dịch với Callback

Hãy xem xét một ví dụ phức tạp hơn. Đây là một phương thức của một đối tượng giao dịch trong Deno DSO. (Tôi là cộng tác viên). Nó được viết bằng TypeScript. TypeScript là một đường cú pháp cho JavaScript cung cấp sự an toàn cho kiểu thời gian biên dịch. TypeScript được biên dịch sang JavaScript. Phương thức này chuyển một lệnh gọi lại đến một máy khách cơ sở dữ liệu dso.client nhận lệnh gọi lại và trong phương thức / hàm cơ sở dữ liệu sẽ xử lý một giao dịch.

static async transaction<T>( processor: (transaction: Transaction) => Promise<T>, ): Promise<T> {
 return (await dso.client.transaction(async (conn) => {
 const trans = new Transaction(conn); 
return await processor(trans); 
})) 
as T; }

Đây là phương thức database transaction. Lưu ý nơi kết nối được chuyển đến bộ xử lý, sau đó sẽ chuyển nó đến đối tượng giao dịch sử dụng nó để quản lý các giao dịch của chúng ta.

`/** * Execute a transaction process, and the transaction successfully * returns the return value of the transaction process * @param processor transaction processor */ 
async transaction<T = any>(processor: TransactionProcessor<T>): Promise<T> { 
return await this.useConnection(async (connection) => { 
try { 
await connection.execute(“BEGIN”); 
const result = await processor(connection);
 await connection.execute(“COMMIT”); return result; 
} catch (error) { 
if (connection.state == ConnectionState.CONNECTED) { log.info(`ROLLBACK: ${error.message}`); 
await connection.execute(“ROLLBACK”); } 
throw error; 
}
 }); }

Sau mã boilerplate ở trên, nơi callback sẽ xuất hiện trong đó là trọng tâm chính của chúng ta. When invoking transaction in this ORM, chúng ta phải chuyển vào logic nghiệp vụ của mình trong một lệnh callback. Chúng ta có thể thấy một lệnh callback lấy một đối tượng giao dịch, sử dụng đối tượng giao dịch đó nhận kết nối cơ sở dữ liệu để thực hiện xử lý giao dịch.

const result = await dso.transaction<boolean>(async trans => {
 const userModel = trans.getModel(UserModel);
 const topicModel = trans.getModel(TopicModel);
userId = await userModel.insert({ nickName: “foo”, password: “bar”, phoneNumber: “08135539123” });
 topicId = await topicModel.insert({ title: “zoo”, userId });
 return true;
});

Cuối cùng

Từ ứng dụng callback rất đơn giản, chúng tôi đã đi đến một cái gì đó quan trọng hơn để cho phép chúng tôi hiểu về việc callback. Đó là một khái niệm cơ bản không thể bỏ qua khi chúng ta muốn làm JavaScript với sự hiểu biết sâu sắc về ngôn ngữ này. Việc hiểu những khái niệm như thế này mang lại cho chúng ta sức mạnh siêu việt để thành thạo trong việc lập trình.

Bài viết gốc tại đây.

Hiện tại khóa học Web Frontend tại Techmaster Vietnam vẫn liên tục tuyển sinh các lớp tiếp theo. Và trong tình hình dịch bệnh phức tạp, lớp sẽ chuyển sang học hình thức trực tuyến có tương tác, thời lượng và chất lượng không đổi, vẫn đảm bảo việc làm cho học viên tốt nghiệp.

Chi tiết khóa học: https://frontend.techmaster.vn/.

Liên hệ tư vấn: Mr Thịnh - 0987273764 (zalo).