Chức năng gọi lại c ++

Gọi lại là một khái niệm không mới. Tuy nhiên, nó là một trong những khái niệm khá khó hiểu và dễ nhầm lẫn trong quá trình thiết lập. Với 1 số bạn có kiến ​​thức cơ bản về C++, Java hay C#, ta thường biết đến callback qua khái niệm delegate (con trỏ hàm)

Bài viết đầu tiên, mình xin giới thiệu gọi lại trong javascript. Lý do chọn javascript là vì Gọi lại trong javascript là đơn giản, dễ hiểu nhất. Bài viết nhắm tới đối tượng là các bạn mới bắt đầu nên mình sẽ cố gắng viết đơn giản nhất có thể

1. callback idea

Đầu tiên, xin nhắc lại đôi chút về gọi lại khá niệm

A callback is a piece of executable code that is passed as 
an argument to other code, which is expected to call back
(execute) the argument at some convenient time.

Nói một cách dễ hiểu, gọi lại tức là ta truyền một đoạn mã (Hàm A) này vào một đoạn mã khác (Hàm B). Đến một thời điểm nào đó, hàm A sẽ bị hàm B gọi lại (callback)

Tới đây các bạn vẫn chưa hiểu? . Mình xin bật ra 1 ví dụ đơn giản dễ hiểu ở phần bên dưới

Chức năng gọi lại c ++

2. Ví dụ về callback. Ứng dụng trong jQuery

Bạn có việc phải đi công tác xa nhà. Bạn tàn vợ, trong thời gian bạn đi, nếu như có ai giao quà tới, hãy đem qua tặng em gái dễ thương hàng xóm. Hàm A ở đây là việc tặng quà cho em hàng xóm

function tangQua(qua) {
   return console.log("Đã tặng " + qua);  
}

Hàm B ở đây là việc vợ bạn ở nhà. Ta truyền hàm A thành 1 đối số cho hàm B, tại 1 thời điểm nào đó, hàm B sẽ gọi hàm A (Đức là vợ bạn mang quà qua cho em hàng xóm)

function oNha(vo, tangQua) {
   var qua = "Quà đã nhận";
   tangQua(qua);  
}

Như các bạn đã thấy, hàm A được truyền vào như 1 đối số. Các bạn đã biết jQuery có thể sử dụng rất nhiều callback mà không biết. Hãy xem xét ví dụ dưới đây, ta sẽ hiển thị 1 cửa sổ bật lên khi nhấp vào 1 nút. Bài viết trước nói về fiddle nên lần này mình sẽ lấy link fiddle làm ví dụ

http. //jsbin. com/potivubifi/1/watch?html,js,đầu ra

Ở đây, hàm showPopup chính là hàm A, còn $(‘#btn’). click() is function B. Hàm B sẽ gọi hàm A khi ta click vào nút. Các bạn thường viết jQuery bằng cách ở bên dưới, nhưng không hiểu bản chất của công việc mình đang làm

3. Ứng dụng của cuộc gọi lại

Như mình đã nói, Javascript là một ngôn ngữ khá thích hợp để gọi lại giới thiệu. Ta có thể chuyển thẳng 1 hàm sang 1 hàm khác, vì trong javascript 1 hàm được xem như 1 đối tượng (object). Trong các ngôn ngữ khác như C#, ta phải sử dụng delegate để chuyển 1 chức năng này sang chức năng khác (Nhớ kỹ câu này, mình sẽ nói rõ hơn ở bài sau)

A number you will ask. Callback mình code có xài mấy đâu? . NET)

Trong JavaScript, một hàm cũng chính là một đối tượng, do đó hàm sẽ mang nhiều tính chất giống với các kiểu dữ liệu thông thường khác như Number, String, Array, … Do đó chúng ta có thể thực hiện những công việc như vậy. lưu trữ hàm trong 1 biến, truyền hàm như một tham số vào của hàm khác, tạo ra 1 hàm bên trong hàm và trả về hàm dưới dạng giá trị trả về

Chính bởi vì khả năng truyền một hàm như là tham số đầu vào của một hàm khác (ta gọi là "hàm-khác" để phân biệt), sau đó nó được gọi là thực thi bên trong "hàm-khác" này, mà ta có . Ngoài ra, ta gọi "hàm-khác" đây là hàm bậc cao hơn

Khái niệm truyền hàm như một tham số thực sự không mới, nó là một khái niệm của lập-trình-hàm (lập trình chức năng). Nếu các bạn đã từng học qua C/C thì chắc hẳn cũng đã biết về khái niệm "con trỏ hàm", khái niệm hàm gọi lại thực hiện kế thừa từ đó, chỉ có điều, mức độ phổ biến của hàm gọi lại trong JavaScript là lớn hơn

Hàm bậc cao và hàm gọi lại là gì?

Nói một cách đơn giản nhất thì

• Hàm bậc cao (hàm bậc cao) là hàm có khả năng hoạt động dựa trên 1 hàm khác, tức là. nó có thể nhận hàm (hàm) làm tham số đầu vào, hoặc sẽ trả về 1 hàm khác. Một trong 2 điều kiện xảy ra thì được gọi là hàm bậc cao

• Hàm gọi lại làm hàm được truyền vào "hàm-khác" như một tham số bắt đầu, sau đó sẽ được gọi là kích hoạt bên trong "hàm-khác" này

Nghe có vẻ khó hiểu, nhưng hãy xem xét các minh hoạ trực quan hơn sau đây

hàm mapArrayString2Length ( originalArray, itemFunction) {

var newArray = [];

var giá trị mới;

tôi;

var len;

for (i = 0, len = originalArray. chiều dài;

newValue = itemFunction( originalArray[ i ]);

Mảng mới. đẩy (giá trị mới);

}

trả về mảng mới;

}

hàm findLength (str)

{

trả lại str. chiều dài

}

Ta thấy, hàm mapArrayString2Length() có nhận một tham số là hàm (tham số itemFunction). Như vậy, hàm mapArrayString2Length() được gọi là hàm bậc cao. Ngoài ra hàm findLength() được truyền vào là 1 tham số, do đó ta gọi hàm findLength() hoặc tham số itemFunction là hàm gọi lại

Chạy đoạn mã thử trên sẽ cho kết quả như sau

var arr_name = [ 'Ronaldo', 'Messi', 'Suarez' ];

var arr_length = map(arr_name, findLength);

Ngoài ra, hãy thử xem thêm một ví dụ về hàm bậc cao có trả về 1 hàm khác sau đây

hàm makeMultiplier( multNum ) {

hàm trả về (num) { return multNum * num };

}

//Truyền "hệ số nhân" tùy ý để tạo ra các hàm khác nhau

var doubler = makeMultiplier(2);

var _3x2_ = nhân đôi(3);

var _4x2_ = nhân đôi(4);

Hàm makeMultiplier() cũng được coi là hàm bậc cao hơn

Gọi lại thường được sử dụng tại bất kỳ vị trí nào trong JavaScript?

Trong JS, nếu xét ở phía client, ngoài những đoạn mã xử lý tuần tự thông thường, ta có 2 hoạt động tương đối khác biệt so với các server ngôn ngữ khác, đó là

• Sự kiện lắng nghe. list as watching sự kiện nhấp chuột, lắng nghe sự kiện key enter, …

• Xử lý bất đồng bộ. Tính năng nổi bật của JS là khả năng xử lý bất đồng bộ, có thể kể đến một vài hoạt động như. call AJAX, read async file format, …

Về phần mã xử lý sự kiện lắng nghe, nếu bạn sử dụng jQuery thì những chức năng gọi lại sẽ có dạng như thế này

//Lắng nghe sự kiện nhấp chuột, hàm xử lý truyền vào chính là 1 cuộc gọi lại

$("#btn_1"). nhấp (hàm () {

alert("Btn 1 Click");

});

Ngoài ra, nếu bạn gọi AJAX, hoặc các xử lý bất đồng bộ tương tự như thế, bạn cũng sẽ sử dụng rất nhiều gọi lại

chức năng gọi lại thành công ( jqXHR ) {

// Làm gì đó nếu thành công

}

hàm errorCallback( jqXHR ) {

// Làm gì đó nếu thành công

}

$. ajax({

url. "http. //vĩ cầm. jshell. mạng/favicon. png",

sự thành công. gọi lại thành công,

lỗi. errorGọi lại

});

Cơ chế hoạt động của Callback

Như đã nói ban đầu, hàm trong JavaScript cũng chính là đối tượng đối tượng, chúng ta có thể truyền hàm vào tham số tương tự như cách chúng ta vẫn làm với các kiểu dữ liệu khác nhau vậy

Xin lưu ý rằng, sự việc khác được quyết định một hàm có được thực thi hay không chính là cặp dấu ngoặc kép (). The method ta report a hàm as after

hàm doS Something (đầu vào) {

// Làm việc gì đó

}

Khi đó, nếu ta chỉ đơn thuần gọi tên hàm doSomething mà không có cặp dấu trích, thì đơn thuần là ta vừa gọi theo định nghĩa của hàm, khi ta gọi doSomething() – có cặp dấu trích – thì khi đó hàm mới được

Vì thế, khi ta truyền hàm đi, ta chỉ đơn thuần sử dụng tên hàm mà không có dấu trích dẫn – tức là chỉ truyền đi định nghĩa hàm – có định nghĩa của hàm thông qua tham số rùi, thì hàm bậc cao hơn muốn sử dụng

Một số vấn đề gặp phải khi sử dụng chức năng gọi lại

Do viện sử dụng hàm trong Javascript tương thích với hoạt động, do đó ta sẽ thường gặp hai vấn đề chính khi sử dụng gọi lại như sau. đảm bảo ngữ cảnh của con trỏ this trong gọi lại, và địa ngục gọi lại (gọi lại địa ngục). Đừng hoảng sợ, chúng ta đều sẽ có công cụ để đối phó với công việc này

Bối cảnh bảo đảm của con trỏ this trong lệnh gọi lại

Có thể bạn đã biết, khi một hàm được kích hoạt, bản thân nó sẽ có một giá trị tham chiếu tới các đối tượng vừa gọi nó, giá trị của nó nằm ở con trỏ này. Như mọi người đã thấy ở trên, ta có thể truyền hàm gọi lại đi bất kỳ đâu ta muốn, tức là đối tượng kích hoạt hàm gọi lại này chính là hàm bậc cao chứa nó. Tuy nhiên, trong nhiều trường hợp khi thiết kế hàm gọi lại, người dùng mong muốn con trỏ this của hàm gọi lại là một đối tượng cụ thể bất kỳ chứ không phải là hàm bậc cao hơn, vì vậy chúng ta phải xử lý lý do nào?

bộ đếm var = {

đếm_số. 0,

đếm dần lên. hàm số(){

cái này. số_số = 1;

}

};

jQuery('#button_count'). nhấp chuột (bộ đếm. đếm dần lên );

Đoạn mã trên bắt sự kiện nhấp chuột vào nút button_count để có thể tăng biến số đếm của bộ đếm. Hàm count_up được chuyển thành hàm gọi lại và vấn đề chính nằm ở điểm này. khi sự kiện nhấp chuột vào button_count được kích hoạt, hàm count_up được gọi nhưng không thể tìm thấy biến này. đếm_số. Lý do là con trỏ this của hàm count_up đang trỏ tới hàm bậc cao hơn gọi nó chứ không phải đối tượng bộ đếm

Để giải quyết vấn đề này, ta phải chỉ định rõ ngữ cảnh của lệnh gọi lại hàm ngay từ khi truyền vào. JavaScript cung cấp cho ta 3 công cụ là bind(), call() và apply(). Trong lần này, ta sẽ sử dụng bind()

jQuery('#button_count'). nhấp chuột (bộ đếm. đếm dần lên. liên kết (bộ đếm));

Rất nhiều lỗi xảy ra khi chúng tôi không chủ động kiểm tra tốt bối cảnh của hàm gọi lại khi gọi, vì vậy hãy chú ý đến công việc này mỗi khi có ý định sử dụng gọi lại

Địa ngục gọi lại (gọi lại địa ngục)

Như chúng ta đã biết, hàm gọi lại được thực thi bên trong một hàm khác, nếu ta tiếp tục có hàm gọi lại bên trong một hàm gọi lại khác thì thế nào? . Thứ quái quỷ này được gọi là địa ngục gọi lại (hay địa ngục gọi lại). Bạn sẽ rất hay gặp vấn đề này khi xử lý các lệnh bất đồng bộ, kiểu như

p_client. mở (chức năng (err, p_client) {

p_client. dropDatabase(function(err, done) {

p_client. createCollection('test_custom_key', function(err, collection) {

thu thập. chèn ({'a'. 1}, chức năng (err, tài liệu) {

//

// and many callback nữa

});

});

});

});

Khi callback hell xuất hiện, xử lý logic lí trí của chương trình sẽ trở nên cực kỳ phức tạp và khó bắt, khi có lỗi xảy ra thì rất khó để gỡ lỗi cũng như giải quyết. Bên cạnh đó, callback hell cũng làm cho tính thẩm mỹ của code giảm đi đáng kể, khó đọc, khó quản lý,… Dưới đây là hai giải pháp cho callback hell

• If is used callback. ta nên khai báo từng hàm gọi lại riêng biệt với cụ thể, sau đó gọi tên hàm gọi lại đầu tiên. Cách này tuy làm thẩm mỹ code nhìn tốt hơn một chút nhưng thực tế thì code vẫn còn rất tệ và khó đọc

• Sử dụng kỹ thuật chạy bất đồng bộ khác. Có thể sử dụng kỹ thuật Promise, async và await, … Các kỹ thuật này giải quyết triệt để gọi lại địa ngục, mình khuyên mọi người nên tìm hiểu các kỹ thuật này. Chỉ mất 1 chút thời gian tìm hiểu nhưng lợi ích có được là rất rất nhiều

Kết luận

Xuyên xuốt phần trình bày vừa rồi, mọi người đã có thể hiểu được khái niệm gọi lại trong Javascript là gì, thấy được sự linh hoạt và tính năng mạnh mẽ của nó, ngoài ra những vị trí thường được ứng dụng kỹ thuật gọi lại cũng đã được

Hàm callback rất linh hoạt và hữu dụng, tuy nhiên nó cũng có những hạn chế nhất định, hi vọng mọi người có thể nắm bắt được những hạn chế của nó và một vài cách khắc phục phổ biến và hiệu quả

theo kipalog. com

BizFly Cloud là nhà cung cấp dịch vụ điện toán đám mây đám mây với chi phí thấp, được vận hành bởi VCCorp.

BizFly Cloud là một trong 4 doanh nghiệp nòng cốt trong "Chiến dịch kết thúc chuyển đổi số bằng công nghệ điện toán đám mây Việt Nam" của Bộ TT&TT;