ฟังก์ชั่นโทรกลับคืออะไร?


684

ฟังก์ชั่นโทรกลับคืออะไร?


8
คุณสามารถค้นหาได้ที่นี่: stackoverflow.com/a/9652434/3343174คำอธิบายที่ดีที่สุดเกี่ยวกับการโทรกลับ
Fakher


ดูคำตอบที่สองสำหรับคำอธิบายรายละเอียด
Donato

คำอธิบายที่ดีที่สุดในการติดต่อกลับที่ฉันเคยพบ youtube.com/watch?v=xHneyv38Jro
Sameer Sinha

คำตอบ:


681

นักพัฒนามักจะสับสนกับสิ่งที่โทรกลับเป็นเพราะชื่อของสิ่งที่ถูกสาป

ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นซึ่งคือ:

  • สามารถเข้าถึงได้โดยฟังก์ชั่นอื่นและ
  • ถูกเรียกใช้หลังจากฟังก์ชั่นแรกถ้าฟังก์ชั่นแรกนั้นเสร็จสมบูรณ์

วิธีที่ดีในการจินตนาการว่าฟังก์ชันการโทรกลับทำงานได้อย่างไรว่าเป็นฟังก์ชันที่เรียกว่า " ที่ด้านหลัง " ของฟังก์ชันที่ส่งผ่านเข้าไป

อาจเป็นชื่อที่ดีกว่าอาจเป็นฟังก์ชัน"โทรหลังจาก"

โครงสร้างนี้มีประโยชน์มากสำหรับการทำงานแบบอะซิงโครนัสซึ่งเราต้องการให้กิจกรรมเกิดขึ้นทุกครั้งที่เหตุการณ์ก่อนหน้านี้เสร็จสิ้น

pseudocode:

// A function which accepts another function as an argument
// (and will automatically invoke that function when it completes - note that there is no explicit call to callbackFunction)
funct printANumber(int number, funct callbackFunction) {
    printout("The number you provided is: " + number);
}

// a function which we will use in a driver function as a callback function
funct printFinishMessage() {
    printout("I have finished printing numbers.");
}

// Driver method
funct event() {
   printANumber(6, printFinishMessage);
}

ผลลัพธ์ถ้าคุณเรียกว่าเหตุการณ์ ():

The number you provided is: 6
I have finished printing numbers.

ลำดับของเอาต์พุตที่นี่มีความสำคัญ เนื่องจากฟังก์ชั่นการโทรกลับถูกเรียกหลังจากนั้น "ฉันพิมพ์หมายเลขเสร็จ" จึงพิมพ์ครั้งสุดท้ายไม่ใช่ครั้งแรก

การโทรกลับถูกเรียกเนื่องจากการใช้งานด้วยภาษาของตัวชี้ หากคุณไม่ได้ใช้งานอย่างใดอย่างหนึ่งไม่ต้องทำงานมากกว่าชื่อ 'โทรกลับ' เพิ่งเข้าใจว่ามันเป็นเพียงชื่อที่ใช้อธิบายวิธีการที่ให้มาเป็นอาร์กิวเมนต์ของวิธีอื่นเช่นเมื่อวิธีการหลักถูกเรียก (เงื่อนไขใด ๆ เช่นการคลิกปุ่ม, ตัวจับเวลาติ๊กเป็นต้น) และเนื้อหาของวิธีการนั้นเสร็จสมบูรณ์ ฟังก์ชันการเรียกกลับถูกเรียกใช้

บางภาษารองรับโครงสร้างที่สนับสนุนฟังก์ชันการเรียกกลับหลายอาร์กิวเมนต์และถูกเรียกโดยยึดตามหน้าที่หลักของฟังก์ชันเสร็จสมบูรณ์ (เช่นมีการโทรกลับหนึ่งครั้งในกรณีที่ฟังก์ชันหลักดำเนินการเสร็จสมบูรณ์แล้วจะถูกเรียกอีกอย่างในกรณีที่ฟังก์ชันหลัก ข้อผิดพลาดเฉพาะ ฯลฯ )


31
ตัวอย่างของคุณยอดเยี่ยม แต่ฉันไม่เห็นว่าทำไมคำศัพท์คือ "การโทรกลับ" เมื่อใดที่มีความหมายOfLife "ถูกเรียกกลับ"
CodyBugstein

4
once its parent method completes, the function which this argument represents is then calledสวัสดีครับเกี่ยวกับ ดังนั้นถ้าฟังก์ชั่นถูกส่งผ่านไปยังฟังก์ชั่นอื่นเป็นอาร์กิวเมนต์ แต่เรียกจากกลางของรันไทม์ฟังก์ชั่นของผู้ปกครองเช่นparent(cb) {dostuff1(); cb(); dostuff2()}นั้นมันจะไม่ถือว่าเป็นcallbackฟังก์ชั่น?
Max Yari

2
@ MaxYari: IMHO ก็ยังถือว่าเป็น callback สิ่งสำคัญที่นี่ก็คือฟังก์ชั่นหลักที่จะใช้ฟังก์ชั่นการป้อนข้อมูล (aka กลับ) อย่างใด มันสามารถเรียกได้ว่าอยู่ตรงกลางหรือตรงปลายหรือถ้าตรงตามเงื่อนไข
Kamran Bigdely

12
@ 8bitjunkie ขอบคุณ - แต่ความหมายของOfLifeถูกเรียกใช้ที่ไหนในฟังก์ชั่น printANumber?
BKSpurgeon

2
สิ่งนี้ไม่เป็นความจริงเลย: "ถูกเรียกใช้โดยอัตโนมัติหลังจากฟังก์ชั่นแรกเสร็จสมบูรณ์" การโทรกลับไม่จำเป็นต้องดำเนินการเลยโดยอัตโนมัติเพียงอย่างเดียว ที่จริงแล้วไม่ใช่เรื่องแปลกที่การเรียกกลับจะเสร็จสมบูรณ์ก่อนที่ฟังก์ชัน parent จะเสร็จสมบูรณ์ ฉันไม่ชอบอย่างมากที่ผู้คนอธิบายการเรียกกลับว่าเป็นฟังก์ชันที่ถูกเรียกใช้งาน "ภายหลัง" มันเป็นเรื่องที่สับสนสำหรับคนที่กำลังเรียนรู้เกี่ยวกับพวกเขา ใส่เพียงแค่การเรียกกลับเป็นเพียงฟังก์ชั่นที่ถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชั่นอื่น ๆ ระยะเวลา คำอธิบายที่ดีกว่าจะรวมถึงการอธิบายว่าทำไมการโทรกลับมากกว่าการอ้างอิงฟังก์ชัน
Jordan

225

คำจำกัดความทึบแสง

ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่คุณให้ไว้กับโค้ดอีกชิ้นหนึ่งซึ่งช่วยให้สามารถเรียกใช้งานโค้ดนั้นได้

ตัวอย่างที่คาดหวัง

ทำไมคุณต้องการทำเช่นนี้? สมมติว่ามีบริการที่คุณต้องเรียกใช้ หากบริการกลับมาทันทีคุณเพียง:

  1. เรียกมันว่า
  2. รอผล
  3. ดำเนินการต่อเมื่อผลลัพธ์เข้ามา

ตัวอย่างเช่นสมมติว่าบริการเป็นfactorialฟังก์ชัน เมื่อคุณต้องการมูลค่า5!คุณจะต้องเรียกใช้factorial(5)และจะเกิดขั้นตอนต่อไปนี้:

  1. ตำแหน่งการดำเนินการปัจจุบันของคุณถูกบันทึกไว้ (ในสแต็ก แต่นั่นไม่สำคัญ)

  2. การประหารชีวิตจะถูกมอบให้ factorial

  3. เมื่อfactorialเสร็จแล้วมันจะวางผลลัพธ์ไว้ที่ใดที่หนึ่งที่คุณสามารถไปถึงได้

  4. การประหารจะกลับมาที่เดิม [1]

ทีนี้สมมติว่าfactorialใช้เวลานานมากเพราะคุณให้จำนวนมากและจำเป็นต้องทำงานในคลัสเตอร์ซูเปอร์คอมพิวเตอร์บางแห่ง สมมติว่าคุณคาดว่าจะใช้เวลา 5 นาทีในการส่งคืนผลลัพธ์ของคุณ คุณสามารถ:

  1. ออกแบบและใช้งานโปรแกรมในเวลากลางคืนเมื่อคุณหลับเพื่อที่คุณจะไม่ได้จ้องหน้าจอครึ่งเวลา

  2. ออกแบบโปรแกรมของคุณให้ทำสิ่งอื่นในขณะที่factorialกำลังทำอยู่

หากคุณเลือกตัวเลือกที่สองการโทรกลับอาจเหมาะกับคุณ

การออกแบบแบบครบวงจร

ในการใช้ประโยชน์จากรูปแบบการโทรกลับสิ่งที่คุณต้องการคือสามารถโทรfactorialด้วยวิธีต่อไปนี้:

factorial(really_big_number, what_to_do_with_the_result)

พารามิเตอร์ที่สองwhat_to_do_with_the_resultเป็นฟังก์ชั่นที่คุณส่งไปfactorialด้วยหวังว่าfactorialจะเรียกผลลัพธ์นั้นก่อนกลับมา

ใช่หมายความว่าfactorialต้องมีการเขียนเพื่อรองรับการโทรกลับ

ตอนนี้สมมติว่าคุณต้องการส่งพารามิเตอร์ไปยังการติดต่อกลับของคุณ ตอนนี้คุณทำไม่ได้เพราะคุณจะไม่เรียกมันว่าfactorialเป็น ดังนั้นfactorialจะต้องมีการเขียนเพื่อให้คุณสามารถส่งพารามิเตอร์ของคุณและมันจะส่งพวกเขาไปยังการโทรกลับของคุณเมื่อมันเรียกมัน อาจมีลักษณะเช่นนี้:

factorial (number, callback, params)
{
    result = number!   // i can make up operators in my pseudocode
    callback (result, params)
}

ตอนนี้ที่factorialอนุญาตรูปแบบนี้แล้วการโทรกลับของคุณอาจมีลักษณะเช่นนี้:

logIt (number, logger)
{
    logger.log(number)
}

และสายของคุณfactorialจะเป็น

factorial(42, logIt, logger)

ถ้าคุณต้องการที่จะกลับมาจากบางสิ่งบางอย่างlogIt? คุณทำไม่ได้เพราะfactorialไม่สนใจมัน

ทำไมไม่สามารถfactorialส่งคืนสิ่งที่โทรกลับของคุณส่งคืนได้

ทำให้ไม่มีการปิดกั้น

เนื่องจากการดำเนินการมีขึ้นเพื่อส่งมอบให้กับการโทรกลับเมื่อfactorialเสร็จสิ้นจึงไม่ควรส่งคืนสิ่งใด ๆ แก่ผู้โทร และในอุดมคติแล้วมันก็จะเริ่มทำงานในเธรด / กระบวนการ / เครื่องอื่นแล้วกลับมาทันทีเพื่อให้คุณสามารถดำเนินการต่อไปได้บางสิ่งเช่นนี้:

factorial(param_1, param_2, ...)
{
    new factorial_worker_task(param_1, param_2, ...);
    return;
}

นี่คือ "การโทรแบบอะซิงโครนัส" ซึ่งหมายความว่าเมื่อคุณเรียกมันจะส่งคืนทันที แต่ยังไม่ได้ทำงานจริง ดังนั้นคุณจำเป็นต้องมีกลไกในการตรวจสอบและเพื่อให้ได้ผลลัพธ์เมื่อเสร็จสิ้นและโปรแกรมของคุณมีความซับซ้อนมากขึ้นในกระบวนการ

และโดยวิธีการใช้รูปแบบนี้factorial_worker_taskสามารถเปิดการโทรกลับของคุณแบบอะซิงโครนัสและกลับมาทันที

แล้วคุณจะทำอย่างไร?

คำตอบคืออยู่ในรูปแบบการโทรกลับ เมื่อใดก็ตามที่คุณต้องการเขียน

a = f()
g(a)

และfจะเรียกว่าแบบอะซิงโครนัสคุณจะเขียนแทน

f(g)

ที่gถูกส่งผ่านเป็นโทรกลับ

สิ่งนี้จะเปลี่ยนแปลงโฟลว์ - ทอพอโลยีของโปรแกรมของคุณเป็นหลัก

ภาษาการเขียนโปรแกรมของคุณสามารถช่วยคุณได้มากโดยให้วิธีการสร้างฟังก์ชั่นการบินได้ทันที ในรหัสเหนือ, ฟังก์ชั่นอาจจะเป็นขนาดเล็กg print (2*a+1)หากภาษาของคุณต้องการให้คุณกำหนดสิ่งนี้เป็นฟังก์ชั่นแยกต่างหากโดยมีชื่อและลายเซ็นที่ไม่จำเป็นทั้งหมดแล้วชีวิตของคุณก็จะไม่เป็นที่พอใจหากคุณใช้รูปแบบนี้มาก

หากในอีกด้านหนึ่งภาษาของคุณอนุญาตให้คุณสร้างลูกแกะแล้วคุณจะมีรูปร่างที่ดีขึ้น จากนั้นคุณจะต้องเขียนบางอย่างเช่น

f( func(a) { print(2*a+1); })

ซึ่งดีกว่ามาก

วิธีการโทรกลับ

คุณจะใช้ฟังก์ชั่นโทรกลับเป็นfactorialอย่างไร คุณสามารถทำได้หลายวิธี

  1. หากฟังก์ชันที่เรียกใช้กำลังทำงานในกระบวนการเดียวกันคุณสามารถส่งตัวชี้ฟังก์ชันได้

  2. หรือบางทีคุณต้องการรักษาพจนานุกรมfn name --> fn ptrในโปรแกรมของคุณซึ่งในกรณีนี้คุณสามารถส่งชื่อได้

  3. บางทีภาษาของคุณอาจอนุญาตให้คุณกำหนดฟังก์ชั่นการใช้งานแทนแลมบ์ดา! ภายในตัวมันกำลังสร้างวัตถุบางอย่างและผ่านตัวชี้ แต่คุณไม่ต้องกังวลเกี่ยวกับสิ่งนั้น

  4. บางทีฟังก์ชั่นที่คุณกำลังเรียกใช้กำลังทำงานอยู่บนเครื่องที่แยกจากกันโดยสิ้นเชิงและคุณกำลังเรียกมันโดยใช้โปรโตคอลเครือข่ายเช่น HTTP คุณสามารถเปิดเผยการเรียกกลับของคุณเป็นฟังก์ชัน HTTP-callable และส่งผ่าน URL

คุณได้รับความคิด

การเพิ่มขึ้นล่าสุดของการเรียกกลับ

ในยุคที่เราเข้าสู่เว็บนี้บริการที่เราเรียกใช้มักจะผ่านเครือข่าย เรามักจะไม่สามารถควบคุมบริการเหล่านั้นได้เช่นเราไม่ได้เขียนพวกเขาเราไม่ดูแลพวกเขาเราไม่สามารถมั่นใจได้ว่าพวกเขาจะขึ้นหรือประสิทธิภาพการทำงาน

แต่เราไม่สามารถคาดหวังให้โปรแกรมของเราบล็อกขณะที่เรากำลังรอให้บริการเหล่านี้ตอบสนอง เมื่อตระหนักถึงสิ่งนี้ผู้ให้บริการมักออกแบบ APIs โดยใช้รูปแบบการโทรกลับ

JavaScript รองรับการโทรกลับได้เป็นอย่างดีเช่นกับ lambdas และ closures และมีกิจกรรมมากมายในโลก JavaScript ทั้งบนเบราว์เซอร์และบนเซิร์ฟเวอร์ มีแม้กระทั่งแพลตฟอร์ม JavaScript ที่พัฒนาขึ้นสำหรับมือถือ

เมื่อเราก้าวไปข้างหน้าพวกเราจำนวนมากขึ้นจะต้องเขียนโค้ดอะซิงโครนัสซึ่งความเข้าใจนี้จะเป็นสิ่งจำเป็น


1
แนวคิดอธิบายได้ดีมาก .. ! :)
piyushGoyal

คำอธิบายที่ดี +1
Lingamurthy CS

1
นี่คือคำตอบที่ดีที่สุดในหมู่คนอื่น ๆ ทั้งหมด กรุณาโหวตมัน
Abhishek Nalin

3
อธิบายได้อย่างสมบูรณ์แบบทุกอย่างถูกอธิบาย ฉันหวังว่าฉันจะสามารถลงคะแนนได้อีกครั้ง
Yogesh Yadav

ใช่ฉันเข้าใจว่า lambas ทำงานในจาวาสคริปต์และทับทิมได้อย่างไร และ java 8 แต่เวอร์ชันเก่าของ java ไม่ได้ใช้ lambas และใช้คลาสแทนและฉันต้องการทราบว่าการเรียกกลับนั้นทำงานอย่างไร ยังเป็นคำตอบที่เหนือกว่าสำหรับคนอื่น ๆ
Donato

97

โปรดทราบว่าการโทรกลับเป็นคำเดียว

หน้าโทรกลับวิกิพีเดียอธิบายได้ดีมาก

อ้างจากหน้าวิกิพีเดีย:

ในการเขียนโปรแกรมคอมพิวเตอร์การเรียกกลับเป็นการอ้างอิงถึงรหัสที่สามารถเรียกใช้งานได้หรือส่วนหนึ่งของรหัสที่สามารถเรียกทำงานได้ซึ่งจะถูกส่งเป็นอาร์กิวเมนต์ไปยังรหัสอื่น สิ่งนี้อนุญาตให้เลเยอร์ซอฟต์แวร์ระดับต่ำกว่าเรียกรูทีนย่อย (หรือฟังก์ชัน) ที่กำหนดในเลเยอร์ระดับสูงกว่า


14
เป็นวิธีที่ดีในการนำเสนอคำตอบ
Chathuranga Chandrasekara

1
และสิ่งนี้ยังนำไปสู่คำตอบในวิธีที่ต่างออกไป คำนาม "callback" คือสิ่งที่ถูก "เรียกกลับ" ในลักษณะเดียวกับที่บางสิ่งที่ผ่านการปิดระบบถูกปิดลงและสิ่งที่ใช้ในการเข้าสู่ระบบคือการเข้าสู่ระบบ
ไม่ระบุชื่อ

22
นี่อาจเป็นความคิดเห็น - โดยทั่วไปมันเป็นลิงก์ไปยัง Wikipedia
CodyBugstein

วิกิพีเดียมีการเขียนโปรแกรมที่ยอดเยี่ยมจริงๆ ฉันมักจะรู้สึกเหมือนคำว่า "โทรกลับ" ได้รับการอธิบายที่ดีที่สุดโดยใช้วลี "ฉันจะโทรกลับไปที่ ... "
โทมัส

คำอธิบายที่ดีเยี่ยมที่javascriptissexy.com/…; ซึ่งฉันจะโพสต์ที่นี่; ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่ถูกส่งผ่านไปยังฟังก์ชั่นอื่นเป็นพารามิเตอร์และฟังก์ชั่นการโทรกลับถูกเรียกหรือดำเนินการภายในฟังก์ชั่นอื่น ๆ // โปรดทราบว่ารายการในพารามิเตอร์ของเมธอดการคลิกเป็นฟังก์ชันไม่ใช่ตัวแปร // รายการนั้นเป็นฟังก์ชันการเรียกกลับ $ ("# btn_1") คลิก (ฟังก์ชั่น () {การแจ้งเตือน ("Btn 1 คลิก") );}); ดังที่คุณเห็นในตัวอย่างก่อนหน้านี้เราส่งผ่านฟังก์ชั่นเป็นพารามิเตอร์ไปยังวิธีการคลิกเพื่อให้ดำเนินการได้ -
MarcoZen

46

การตอบสนองของคนธรรมดาจะเป็นว่ามันเป็นฟังก์ชั่นที่ไม่ได้ถูกเรียกโดยคุณ แต่เป็นโดยผู้ใช้หรือโดยเบราว์เซอร์หลังจากเหตุการณ์บางอย่างเกิดขึ้นหรือหลังจากประมวลผลโค้ดบางส่วนแล้ว


42

ฟังก์ชั่นการโทรกลับเป็นสิ่งที่ควรจะเรียกเมื่อเงื่อนไขตรง แทนที่จะเรียกใช้ทันทีฟังก์ชันเรียกกลับจะถูกเรียกใช้ ณ จุดหนึ่งในอนาคต

โดยทั่วไปจะใช้เมื่อเริ่มงานที่จะเสร็จสิ้นแบบอะซิงโครนัส (เช่นจะเสร็จสิ้นบางเวลาหลังจากที่ฟังก์ชั่นการโทรกลับมา)

ตัวอย่างเช่นฟังก์ชั่นในการร้องขอเว็บเพจอาจต้องการให้ผู้โทรจัดเตรียมฟังก์ชันการโทรกลับที่จะถูกเรียกเมื่อเว็บเพจนั้นดาวน์โหลดเสร็จสิ้น


ในประโยคแรกของคุณคุณพูด"...when a condition is met"แต่ฉันคิดว่าการโทรกลับถูกเรียกเมื่อฟังก์ชั่นผู้ปกครองเสร็จสิ้นการดำเนินการและไม่ได้ขึ้นอยู่กับเงื่อนไข (?)
Ojonugwa Jude Ochalifu

'เงื่อนไขบางประการ' นั้นหมายถึงว่าพวกเขามักถูกเรียกด้วยเหตุผลมากกว่าสุ่ม การเรียกกลับสามารถเรียกได้เมื่อผู้ปกครอง / ผู้สร้างยังคงดำเนินการ - ซึ่งอาจนำไปสู่สภาพการแข่งขันหากโปรแกรมเมอร์ไม่ได้คาดหวัง
Thomas Bratt

โอเคขอบคุณสำหรับการชี้แจง
Ojonugwa Jude Ochalifu

34

คำอธิบายการโทรกลับนั้นง่ายที่สุดในแง่ของระบบโทรศัพท์ ฟังก์ชั่นการโทรนั้นคล้ายคลึงกับการโทรหาใครบางคนทางโทรศัพท์ถามคำถามรับคำตอบและวางสาย การเพิ่มการโทรกลับจะเปลี่ยนการเปรียบเทียบเพื่อให้หลังจากถามคำถามคุณจะให้ชื่อและหมายเลขของเธอแก่เธอเพื่อให้เธอสามารถโทรกลับหาคุณได้

- Paul Jakubik "การดำเนินการติดต่อกลับใน C ++"


1
ดังนั้นชื่อและหมายเลขของฉันคือฟังก์ชั่น?
Koray Tugay

ไม่นั่นคือการเปรียบเทียบหาก "การโทรกลับ" เป็นชื่อที่ดีสำหรับสิ่งที่คุณทำแทน: คุณขอให้ผู้ให้บริการโทรศัพท์โทรออก ตอนจบ.
gherson

33

ฉันเชื่อว่าศัพท์แสง "โทรกลับ" นี้ถูกใช้อย่างไม่เหมาะสมในหลาย ๆ ที่ คำจำกัดความของฉันจะเป็นเช่น:

ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่คุณส่งให้ใครบางคนและให้พวกเขาเรียกมันในบางช่วงเวลา

ฉันคิดว่าผู้คนเพิ่งอ่านประโยคแรกของคำจำกัดความของ wiki:

การเรียกกลับเป็นการอ้างอิงถึงรหัสที่ใช้งานได้หรือส่วนหนึ่งของรหัสที่สามารถเรียกทำงานได้ซึ่งจะถูกส่งเป็นอาร์กิวเมนต์ไปยังรหัสอื่น

ฉันทำงานกับ API จำนวนมากดูตัวอย่างที่ไม่ดีมากมาย หลายคนมักจะตั้งชื่อตัวชี้ฟังก์ชั่น (การอ้างอิงถึงรหัสที่เรียกใช้งานได้) หรือฟังก์ชั่นที่ไม่ระบุชื่อ (ส่วนหนึ่งของรหัสที่เรียกใช้งานได้) "โทรกลับ" หากพวกเขาเป็นเพียงแค่ฟังก์ชั่น

จริงๆแล้วประโยคที่สองในคำจำกัดความของ wiki แสดงความแตกต่างระหว่างฟังก์ชั่นการโทรกลับและฟังก์ชั่นปกติ:

สิ่งนี้อนุญาตให้เลเยอร์ซอฟต์แวร์ระดับต่ำกว่าเรียกรูทีนย่อย (หรือฟังก์ชัน) ที่กำหนดในเลเยอร์ระดับสูงกว่า

ดังนั้นความแตกต่างคือสิ่งที่คุณกำลังจะผ่านฟังก์ชั่นและวิธีการที่คุณส่งผ่านฟังก์ชั่นจะถูกเรียกว่า หากคุณเพียงแค่กำหนดฟังก์ชั่นและส่งไปยังฟังก์ชั่นอื่นและเรียกมันโดยตรงในส่วนของฟังก์ชั่นนั้นอย่าเรียกมันว่า callback คำจำกัดความกล่าวว่าฟังก์ชั่นที่ส่งผ่านของคุณจะถูกเรียกโดยฟังก์ชัน "ระดับต่ำกว่า"

ฉันหวังว่าผู้คนสามารถหยุดใช้คำนี้ในบริบทที่คลุมเครือมันไม่สามารถช่วยให้ผู้คนเข้าใจดียิ่งขึ้นเท่านั้น


2
คำตอบของคุณเหมาะสม ... แต่ฉันมีปัญหาในการนึกภาพ คุณยกตัวอย่างได้ไหม
CodyBugstein

3
@ Zane Wong :: ในที่สุดคุณได้เขียน "คำจำกัดความที่บอกว่าฟังก์ชั่นที่ส่งผ่านของคุณจะถูกเรียกโดยฟังก์ชัน" ระดับต่ำกว่า " คุณช่วยอธิบายสิ่งที่ฟังก์ชั่นระดับล่างได้หรือไม่ มันจะดีกว่าถ้าคุณยกตัวอย่าง
Viku

ตัวอย่างน่าจะดี
Yousuf Azad

1
ฉันคิดว่าความแตกต่างระหว่างการเรียกฟังก์ชั่นแบบคลาสสิคและสไตล์การโทรกลับคือลิงก์ไปยังทิศทางที่พึ่งพา: ถ้าโมดูล A ขึ้นอยู่กับ ("ใช้") โมดูล B, A เรียกใช้ฟังก์ชันของ B ไม่ใช่การเรียกกลับ ถ้า A ส่งการอ้างอิงไปยังฟังก์ชันของเขาไปที่ B ดังนั้น B จะเรียกใช้ฟังก์ชันของ A นี่คือการเรียกกลับ: การโทรกลับไปเปรียบเทียบกับการพึ่งพาโมดูล
XouDo

30

มาทำให้มันง่าย ฟังก์ชั่นโทรกลับคืออะไร?

ตัวอย่างโดยคำอุปมาและอุปมา

ฉันมีเลขา ทุกวันฉันขอให้เธอ: (i) ย่อหย่อนอีเมลขาออกของ บริษัท ที่ที่ทำการไปรษณีย์และหลังจากที่เธอทำนั้นต้องทำ: (ii) สิ่งที่ผมเขียนงานสำหรับเธอที่หนึ่งในผู้บันทึกเหนียว

ทีนี้งานในโน้ตย่อคืออะไร? งานนั้นแตกต่างกันไปในแต่ละวัน

สมมติว่าในวันนี้ฉันต้องการให้เธอพิมพ์เอกสารบางอย่างออกมา ดังนั้นฉันจึงเขียนมันลงบนกระดาษโน๊ตและฉันตรึงมันไว้บนโต๊ะของเธอพร้อมกับจดหมายขาออกที่เธอต้องการโพสต์

สรุป:

  1. ก่อนอื่นเธอต้องย่อหย่อนจดหมายและ
  2. ทันทีหลังจากนั้นเธอต้องพิมพ์เอกสารบางอย่าง

ฟังก์ชั่นการโทรกลับเป็นหน้าที่ที่สอง: การพิมพ์เอกสารเหล่านั้น เพราะมันจะทำหลังจากที่จดหมายถูกส่งไปและเพราะโน้ตที่บอกให้เธอพิมพ์เอกสารนั้นจะมอบให้เธอพร้อมกับจดหมายที่เธอต้องการโพสต์

ตอนนี้เรามาผูกคำศัพท์กับการเขียนโปรแกรมกัน

  • ชื่อวิธีการในกรณีนี้คือ: DropOffMail
  • และฟังก์ชั่นการโทรกลับคือ: PrintOffDocuments PrintOffDocuments เป็นฟังก์ชั่นโทรกลับเพราะเราต้องการให้เลขาทำเช่นนั้นหลังจาก DropOffMail ทำงาน
  • ดังนั้นฉันจะ "ผ่าน: PrintOffDocuments เป็น" อาร์กิวเมนต์ "กับวิธี DropOffMail นี่คือจุดสำคัญ

นั่นคือทั้งหมดที่มันเป็น ไม่มีอะไรเพิ่มเติม ฉันหวังว่าจะลบล้างมันสำหรับคุณ - และถ้าไม่ใช่ให้โพสต์ความคิดเห็นและฉันจะพยายามอย่างเต็มที่เพื่ออธิบาย


18

สิ่งนี้ทำให้การเรียกกลับมีเสียงเหมือนคำสั่ง return ในตอนท้ายของเมธอด

ฉันไม่แน่ใจว่าเป็นสิ่งที่พวกเขา

ฉันคิดว่าการเรียกกลับเป็นจริงการเรียกไปยังฟังก์ชั่นเป็นผลมาจากฟังก์ชั่นอื่นจะถูกเรียกใช้และเสร็จสิ้น

ฉันยังคิดว่าการโทรกลับมีจุดประสงค์เพื่อกล่าวคำปราศรัยที่เกิดขึ้นในรูปแบบของ "เฮ้! สิ่งที่คุณขอใช่ไหมฉันทำไปแล้ว - แค่คิดว่าฉันจะให้คุณรู้ - กลับไปหาคุณ"


1
+1 สำหรับการตั้งคำถามการโทรกลับและรายงานการคืนสินค้า ฉันเคยชินกับสิ่งนี้และผู้สำเร็จการศึกษาจำนวนมากที่ฉันทำงานด้วย
8bitjunkie

2
คำตอบที่ดี - ช่วยฉันเข้าใจว่าไม่เหมือนคำตอบอื่น ๆ อีกมากมาย!
adaam

18

โทรกลับคืออะไร

  • โดยทั่วไปแล้วจะมีการโทรศัพท์ติดต่อเพื่อรับสายที่ใครบางคนได้รับ
  • ในการคำนวณการเรียกกลับเป็นส่วนหนึ่งของรหัสปฏิบัติการที่ถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังรหัสอื่น เมื่อฟังก์ชั่นเสร็จสิ้นกับการทำงานของมัน (หรือเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น) มันจะเรียกการโทรกลับของคุณ (มันจะโทรกลับคุณ - ดังนั้นชื่อ) ฟังก์ชั่น

คืออะไรฟังก์ชันการเรียกกลับ ?

  • ฟังก์ชั่นการโทรกลับเป็นเหมือนคนรับใช้ที่ "โทรกลับ" ถึงอาจารย์ของเขาเมื่อเขาทำงานเสร็จแล้ว
  • ฟังก์ชันการเรียกกลับเป็นฟังก์ชันที่ถูกส่งไปยังฟังก์ชั่นอื่น (ขอเรียกสิ่งนี้ว่าฟังก์ชั่นอื่น ๆotherFunction) เป็นพารามิเตอร์และฟังก์ชันการเรียกกลับที่เรียกว่า (หรือดำเนินการ) otherFunctionภายใน
    function action(x, y, callback) {
        return callback(x, y);
    }

    function multiplication(x, y) {
        return x * y;
    }

    function addition(x, y) {
        return x + y;
    }

    alert(action(10, 10, multiplication)); // output: 100

    alert(action(10, 10, addition)); // output: 20

ใน SOA การเรียกกลับอนุญาตให้โมดูลปลั๊กอินเข้าถึงบริการจากคอนเทนเนอร์ / สภาพแวดล้อม

ความคล้ายคลึง: การโทรกลับ ไม่ตรงกัน ไม่มีการปิดกั้น
ตัวอย่างชีวิตจริงสำหรับการโทรกลับ


ฟังก์ชันการเรียกกลับไม่ใช่ฟังก์ชันลำดับที่สูงกว่า มันถูกส่งผ่านไปยังฟังก์ชันลำดับสูงกว่า
danio

17

โทรหลังจากที่จะเป็นชื่อที่ดีกว่าชื่อโง่, โทรกลับ เมื่อหรือเงื่อนไขตรงกับภายในฟังก์ชั่นให้เรียกฟังก์ชั่นอื่นฟังก์ชั่นการโทรหลังจากที่หนึ่งที่ได้รับเป็นข้อโต้แย้ง

แทนที่จะเขียนโค้ดฟังก์ชั่นด้านในฟังก์ชั่นหนึ่งฟังก์ชั่นหนึ่งเขียนฟังก์ชั่นเพื่อยอมรับฟังก์ชั่นการโทรหลังจากที่เขียนแล้วเป็นอาร์กิวเมนต์ การเรียกหลังจากนั้นอาจถูกเรียกขึ้นอยู่กับการเปลี่ยนแปลงสถานะที่ตรวจพบโดยรหัสในฟังก์ชันที่รับอาร์กิวเมนต์


นี่เป็นความคิดที่ดี ฉันไปที่ "เรียกที่ด้านหลัง" เพื่อลองและอธิบายสิ่งนี้ ฉันเห็นคนอย่าง Martin Fowler ที่นิยมใช้คำว่า "call after" เป็นคำศัพท์ใหม่ในบล็อกเซมินารี
8bitjunkie

15

ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่คุณระบุให้กับฟังก์ชั่น / วิธีการที่มีอยู่ที่จะเรียกใช้เมื่อการดำเนินการเสร็จสมบูรณ์ต้องมีการประมวลผลเพิ่มเติม ฯลฯ

ยกตัวอย่างเช่นใน Javascript หรือ jQuery ที่เจาะจงมากขึ้นคุณสามารถระบุอาร์กิวเมนต์การเรียกกลับที่จะถูกเรียกเมื่อภาพเคลื่อนไหวสิ้นสุดลง

ใน PHP preg_replace_callback()ฟังก์ชั่นช่วยให้คุณสามารถระบุฟังก์ชั่นที่จะถูกเรียกเมื่อจับคู่นิพจน์ปกติผ่านสตริงที่จับคู่กันเป็นอาร์กิวเมนต์


10

ดูรูป :)นี่คือวิธีการทำงาน

โปรแกรมหลักเรียกใช้ฟังก์ชันไลบรารี (ซึ่งอาจเป็นฟังก์ชันระดับระบบด้วย) พร้อมชื่อฟังก์ชันเรียกกลับ ฟังก์ชันการเรียกกลับนี้อาจมีการใช้งานหลายวิธี โปรแกรมหลักเลือกหนึ่งการโทรกลับตามความต้องการ

ในที่สุดฟังก์ชั่นห้องสมุดเรียกฟังก์ชั่นการโทรกลับในระหว่างการดำเนินการ


7
คุณจะเพิ่มคำอธิบายข้อความให้กับสิ่งนี้ด้วยหรือไม่ หากภาพหายไปคำตอบนี้จะสูญเสียบริบททั้งหมด
Tim Post

ข้อความจากบุคคลอื่นอธิบายได้ดีที่สุด สิ่งเดียวที่ฉันรู้สึกคือขาดคือรูปภาพ :)

จากคำอธิบายที่ยืดยาวทั้งหมดที่ฉันได้เห็นที่นี่อันนี้เป็นคำที่ทำให้ฉันไป "ahhhhh ตอนนี้ฉันเห็นการใช้งาน" มี upvote
DiBosco

7

คำตอบง่ายๆสำหรับคำถามนี้คือฟังก์ชันการเรียกกลับเป็นฟังก์ชันที่เรียกใช้ผ่านตัวชี้ฟังก์ชัน หากคุณผ่านตัวชี้ (ที่อยู่) ของฟังก์ชั่นเป็นอาร์กิวเมนต์ไปยังอีกเมื่อตัวชี้นั้นจะใช้ในการเรียกฟังก์ชั่นมันจะชี้ไปที่มันจะบอกว่ามีการโทรกลับจะทำ


7

สมมติว่าเรามีฟังก์ชั่นsort(int *arraytobesorted,void (*algorithmchosen)(void))ที่สามารถรับฟังก์ชั่นตัวชี้เป็นอาร์กิวเมนต์ซึ่งสามารถนำมาใช้ในsort()การดำเนินงานของบางจุด จากนั้นที่นี่รหัสที่จะถูกแก้ไขโดยตัวชี้ฟังก์ชั่นalgorithmchosenเรียกว่าเป็นฟังก์ชั่นการโทรกลับฟังก์ชั่นการโทรกลับ

และดูข้อได้เปรียบคือเราสามารถเลือกอัลกอริทึมเช่น:

  1.    algorithmchosen = bubblesort
  2.    algorithmchosen = heapsort
  3.    algorithmchosen = mergesort   ...

ซึ่งกล่าวได้ถูกนำไปใช้กับต้นแบบ:

  1.   `void bubblesort(void)`
  2.   `void heapsort(void)`
  3.   `void mergesort(void)`   ...

นี่เป็นแนวคิดที่ใช้ในการบรรลุความหลากหลายในการเขียนโปรแกรมเชิงวัตถุ


คำอธิบายที่ดีเยี่ยมที่javascriptissexy.com/…; ซึ่งฉันจะโพสต์ที่นี่; ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่ถูกส่งผ่านไปยังฟังก์ชั่นอื่นเป็นพารามิเตอร์และฟังก์ชั่นการโทรกลับถูกเรียกหรือดำเนินการภายในฟังก์ชั่นอื่น ๆ // โปรดทราบว่ารายการในพารามิเตอร์ของวิธีการคลิกเป็นฟังก์ชั่นไม่ใช่ตัวแปร // รายการนั้นเป็นฟังก์ชันการโทรกลับ $ ("# btn_1") คลิก (ฟังก์ชั่น () {การแจ้งเตือน ("Btn 1 คลิก") );}); ดังที่คุณเห็นในตัวอย่างก่อนหน้านี้เราส่งผ่านฟังก์ชั่นเป็นพารามิเตอร์ไปยังวิธีการคลิกเพื่อให้ดำเนินการ -
MarcoZen

4

“ ในการเขียนโปรแกรมคอมพิวเตอร์การเรียกกลับเป็นการอ้างอิงถึงรหัสที่ใช้งานได้หรือส่วนหนึ่งของรหัสที่สามารถเรียกทำงานได้ซึ่งจะถูกส่งเป็นอาร์กิวเมนต์ไปยังรหัสอื่น สิ่งนี้อนุญาตให้เลเยอร์ซอฟต์แวร์ระดับต่ำกว่าเรียกรูทีนย่อย (หรือฟังก์ชัน) ที่กำหนดในเลเยอร์ระดับสูงกว่า” - วิกิพีเดีย

โทรกลับใน C โดยใช้ฟังก์ชั่นตัวชี้

ใน C การเรียกกลับถูกนำไปใช้โดยใช้ Function Pointer ตัวชี้ฟังก์ชั่น - ตามชื่อแนะนำเป็นตัวชี้ไปยังฟังก์ชั่น

ตัวอย่างเช่น int (* ptrFunc) ();

ที่นี่ ptrFunc เป็นตัวชี้ไปยังฟังก์ชั่นที่ไม่มีข้อโต้แย้งและส่งกลับจำนวนเต็ม อย่าลืมใส่ในวงเล็บมิฉะนั้นคอมไพเลอร์จะถือว่า ptrFunc เป็นชื่อฟังก์ชั่นปกติซึ่งไม่ทำอะไรเลยและส่งกลับตัวชี้ไปที่จำนวนเต็ม

นี่คือรหัสบางส่วนเพื่อแสดงให้เห็นถึงตัวชี้ฟังก์ชั่น

#include<stdio.h>
int func(int, int);
int main(void)
{
    int result1,result2;
    /* declaring a pointer to a function which takes
       two int arguments and returns an integer as result */
    int (*ptrFunc)(int,int);

    /* assigning ptrFunc to func's address */                    
    ptrFunc=func;

    /* calling func() through explicit dereference */
    result1 = (*ptrFunc)(10,20);

    /* calling func() through implicit dereference */        
    result2 = ptrFunc(10,20);            
    printf("result1 = %d result2 = %d\n",result1,result2);
    return 0;
}

int func(int x, int y)
{
    return x+y;
}

ตอนนี้ให้เราพยายามที่จะเข้าใจแนวคิดของการโทรกลับใน C โดยใช้ตัวชี้ฟังก์ชั่น

โปรแกรมที่สมบูรณ์มีสามไฟล์: callback.c, reg_callback.h และ reg_callback.c

/* callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* callback function definition goes here */
void my_callback(void)
{
    printf("inside my_callback\n");
}

int main(void)
{
    /* initialize function pointer to
    my_callback */
    callback ptr_my_callback=my_callback;                        
    printf("This is a program demonstrating function callback\n");
    /* register our callback function */
    register_callback(ptr_my_callback);                          
    printf("back inside main program\n");
    return 0;
}

/* reg_callback.h */
typedef void (*callback)(void);
void register_callback(callback ptr_reg_callback);


/* reg_callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* registration goes here */
void register_callback(callback ptr_reg_callback)
{
    printf("inside register_callback\n");
    /* calling our callback function my_callback */
    (*ptr_reg_callback)();                               
}

ถ้าเรารันโปรแกรมนี้ผลลัพธ์จะเป็น

นี่คือโปรแกรมที่แสดงฟังก์ชันการเรียกกลับภายใน register_callback ด้านใน my_callback ด้านหลังในโปรแกรมหลัก

ฟังก์ชันเลเยอร์ที่สูงกว่าเรียกฟังก์ชันเลเยอร์ที่ต่ำกว่าเป็นการโทรปกติและกลไกการเรียกกลับช่วยให้ฟังก์ชันเลเยอร์ที่ต่ำกว่าเรียกฟังก์ชันเลเยอร์ที่สูงขึ้นผ่านตัวชี้ไปยังฟังก์ชันการเรียกกลับ

การโทรกลับใน Java โดยใช้อินเตอร์เฟส

Java ไม่ได้มีแนวคิดของตัวชี้ฟังก์ชั่นมันใช้กลไกการโทรกลับผ่านกลไกอินเตอร์เฟซที่นี่แทนที่จะเป็นตัวชี้ฟังก์ชั่นเราประกาศอินเตอร์เฟซที่มีวิธีการซึ่งจะถูกเรียกเมื่อ callee เสร็จสิ้นภารกิจของมัน

ให้ฉันสาธิตผ่านตัวอย่าง:

อินเตอร์เฟสการติดต่อกลับ

public interface Callback
{
    public void notify(Result result);
}

ผู้เรียกหรือระดับที่สูงขึ้น

public Class Caller implements Callback
{
Callee ce = new Callee(this); //pass self to the callee

//Other functionality
//Call the Asynctask
ce.doAsynctask();

public void notify(Result result){
//Got the result after the callee has finished the task
//Can do whatever i want with the result
}
}

ฟังก์ชัน Callee หรือฟังก์ชันเลเยอร์ที่ต่ำกว่า

public Class Callee {
Callback cb;
Callee(Callback cb){
this.cb = cb;
}

doAsynctask(){
//do the long running task
//get the result
cb.notify(result);//after the task is completed, notify the caller
}
}

การโทรกลับโดยใช้รูปแบบ EventListener

  • รายการสินค้า

รูปแบบนี้ใช้เพื่อแจ้งจำนวนผู้สังเกตการณ์ / ผู้ฟังจำนวน 0 ถึง n ว่างานเฉพาะได้เสร็จสิ้นแล้ว

  • รายการสินค้า

ความแตกต่างระหว่างกลไกการโทรกลับและกลไก EventListener / Observer คือในการติดต่อกลับผู้แจ้งเตือนจะแจ้งผู้โทรเพียงคนเดียวในขณะที่ผู้จัดกิจกรรมผู้สังเกตการณ์ / ผู้สังเกตการณ์สามารถแจ้งผู้ที่สนใจเหตุการณ์นั้นได้ (การแจ้งเตือนอาจไปยังส่วนอื่น ๆ ของ แอปพลิเคชั่นที่ไม่ได้ทริกเกอร์งาน)

ให้ฉันอธิบายผ่านตัวอย่าง

อินเทอร์เฟซเหตุการณ์

public interface Events {

public void clickEvent();
public void longClickEvent();
}

วิดเจ็ตชั้นเรียน

package com.som_itsolutions.training.java.exampleeventlistener;

import java.util.ArrayList;
import java.util.Iterator;

public class Widget implements Events{

    ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
    ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();

    @Override
    public void clickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                while(it.hasNext()){
                    OnClickEventListener li = it.next();
                    li.onClick(this);
                }   
    }
    @Override
    public void longClickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
        while(it.hasNext()){
            OnLongClickEventListener li = it.next();
            li.onLongClick(this);
        }

    }

    public interface OnClickEventListener
    {
        public void onClick (Widget source);
    }

    public interface OnLongClickEventListener
    {
        public void onLongClick (Widget source);
    }

    public void setOnClickEventListner(OnClickEventListener li){
        mClickEventListener.add(li);
    }
    public void setOnLongClickEventListner(OnLongClickEventListener li){
        mLongClickEventListener.add(li);
    }
}

ปุ่มคลาส

public class Button extends Widget{
private String mButtonText;
public Button (){
} 
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}

ช่องทำเครื่องหมายคลาส

public class CheckBox extends Widget{
private boolean checked;
public CheckBox() {
checked = false;
}
public boolean isChecked(){
return (checked == true);
}
public void setCheck(boolean checked){
this.checked = checked;
}
}

ชั้นเรียนกิจกรรม

แพ็คเกจ com.som_itsolutions.training.java.exampleeventlistener;

public class Activity implements Widget.OnClickEventListener
{
    public Button mButton;
    public CheckBox mCheckBox;
    private static Activity mActivityHandler;
    public static Activity getActivityHandle(){
        return mActivityHandler;
    }
    public Activity ()
    {
        mActivityHandler = this;
        mButton = new Button();
        mButton.setOnClickEventListner(this);
        mCheckBox = new CheckBox();
        mCheckBox.setOnClickEventListner(this);
        } 
    public void onClick (Widget source)
    {
        if(source == mButton){
            mButton.setButtonText("Thank you for clicking me...");
            System.out.println(((Button) mButton).getButtonText());
        }
        if(source == mCheckBox){
            if(mCheckBox.isChecked()==false){
                mCheckBox.setCheck(true);
                System.out.println("The checkbox is checked...");
            }
            else{
                mCheckBox.setCheck(false);
                System.out.println("The checkbox is not checked...");
            }       
        }
    }
    public void doSomeWork(Widget source){
        source.clickEvent();
    }   
}

ชั้นอื่น ๆ

public class OtherClass implements Widget.OnClickEventListener{
Button mButton;
public OtherClass(){
mButton = Activity.getActivityHandle().mButton;
mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
}
@Override
public void onClick(Widget source) {
if(source == mButton){
System.out.println("Other Class has also received the event notification...");
}
}

ชั้นเรียนหลัก

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Activity a = new Activity();
OtherClass o = new OtherClass();
a.doSomeWork(a.mButton);
a.doSomeWork(a.mCheckBox);
}
}

ดังที่คุณเห็นจากโค้ดด้านบนเรามีอินเทอร์เฟซที่เรียกว่าเหตุการณ์ซึ่งโดยทั่วไปจะแสดงรายการเหตุการณ์ทั้งหมดที่อาจเกิดขึ้นสำหรับแอปพลิเคชันของเรา คลาส Widget เป็นคลาสพื้นฐานสำหรับส่วนประกอบ UI ทั้งหมดเช่นปุ่ม, ช่องทำเครื่องหมาย ส่วนประกอบ UI เหล่านี้เป็นวัตถุที่รับเหตุการณ์จากรหัสเฟรมเวิร์ก คลาสวิดเจ็ตใช้อินเทอร์เฟซเหตุการณ์และมีอินเทอร์เฟซซ้อนกันสองรายการ ได้แก่ OnClickEventListener & OnLongClickEventListener

อินเทอร์เฟซสองเหล่านี้มีหน้าที่รับผิดชอบในการรับฟังเหตุการณ์ที่อาจเกิดขึ้นกับส่วนประกอบ UI ที่ได้รับจาก Widget เช่นปุ่มหรือช่องทำเครื่องหมาย ดังนั้นหากเราเปรียบเทียบตัวอย่างนี้กับตัวอย่างการติดต่อกลับก่อนหน้านี้โดยใช้ Java Interface ทั้งสองอินเตอร์เฟสนี้จะทำงานเป็นอินเตอร์เฟสการติดต่อกลับ ดังนั้นรหัสระดับที่สูงขึ้น (กิจกรรมที่นี่) จะใช้อินเทอร์เฟซทั้งสองนี้ และเมื่อใดก็ตามที่มีเหตุการณ์เกิดขึ้นกับวิดเจ็ตรหัสระดับที่สูงขึ้น (หรือวิธีการของอินเทอร์เฟซเหล่านี้ถูกนำไปใช้ในรหัสระดับที่สูงกว่าซึ่งเป็นที่นี่กิจกรรม) จะถูกเรียก

ตอนนี้ให้ฉันพูดถึงความแตกต่างพื้นฐานระหว่างรูปแบบการโทรกลับและ Eventlistener ดังที่เราได้กล่าวไปแล้วว่าการใช้การโทรกลับผู้ใช้สามารถแจ้งเตือนได้เพียงผู้โทรเดียว แต่ในกรณีของรูปแบบ EventListener ส่วนอื่น ๆ หรือคลาสของแอปพลิเคชันสามารถลงทะเบียนสำหรับเหตุการณ์ที่อาจเกิดขึ้นในปุ่มหรือช่องทำเครื่องหมาย ตัวอย่างของคลาสประเภทนี้คือ OtherClass หากคุณเห็นรหัสของ OtherClass คุณจะพบว่ามันได้ลงทะเบียนตัวเองเป็นผู้ฟังของ ClickEvent ที่อาจเกิดขึ้นในปุ่มที่กำหนดไว้ในกิจกรรม ส่วนที่น่าสนใจคือนอกเหนือจากกิจกรรม (ตัวเรียก), OtherClass นี้จะได้รับการแจ้งเตือนเมื่อใดก็ตามที่มีเหตุการณ์การคลิกเกิดขึ้นบนปุ่ม


โปรดเชื่อมโยงหลีกเลี่ยงคำตอบเท่านั้น คำตอบที่ "แทบจะไม่มากกว่าการเชื่อมโยงไปยังเว็บไซต์ภายนอก” อาจถูกลบ .
เควนติน

3

ฟังก์ชั่นการโทรกลับเป็นฟังก์ชั่นที่คุณผ่าน (เป็นข้อมูลอ้างอิงหรือตัวชี้) ไปยังฟังก์ชั่นหรือวัตถุบางอย่าง ฟังก์ชั่นหรือวัตถุนี้จะเรียกฟังก์ชั่นนี้กลับมาในภายหลังได้ตลอดเวลาอาจเป็นไปได้หลายครั้งเพื่อวัตถุประสงค์ใด ๆ :

  • แจ้งการสิ้นสุดของงาน
  • ขอเปรียบเทียบระหว่างสองรายการ (เช่นใน c qsort ())
  • การรายงานความคืบหน้าของกระบวนการ
  • การแจ้งเตือนเหตุการณ์
  • การมอบหมายการเริ่มต้นของวัตถุ
  • การมอบหมายภาพวาดของพื้นที่

...

ดังนั้นการอธิบายการเรียกกลับเป็นฟังก์ชั่นที่ถูกเรียกเมื่อสิ้นสุดฟังก์ชั่นหรืองานอื่นนั้นทำให้มันง่ายเกินไป (แม้ว่าจะเป็นกรณีการใช้งานทั่วไป)


2

การเรียกกลับเป็นแนวคิดของการส่งผ่านฟังก์ชันเป็นพารามิเตอร์ไปยังฟังก์ชันอื่นและเรียกใช้ฟังก์ชันนี้เมื่อกระบวนการเสร็จสมบูรณ์

หากคุณได้แนวคิดในการติดต่อกลับผ่านคำตอบที่ดีเยี่ยมฉันขอแนะนำให้คุณเรียนรู้พื้นฐานของแนวคิดนี้

"อะไรทำให้พวกเขา (นักวิทยาศาสตร์คอมพิวเตอร์) พัฒนาการโทรกลับ?" คุณอาจเรียนรู้ปัญหาที่กำลังบล็อค (โดยเฉพาะการปิดกั้น UI) และการโทรกลับไม่ใช่วิธีแก้ไขปัญหาเดียวเท่านั้น มีวิธีแก้ไขปัญหาอื่น ๆ อีกมากมาย (เช่น Thread, Futures, Promises ... )


1

พื้นที่ใช้งานที่สำคัญอย่างหนึ่งคือคุณลงทะเบียนหนึ่งในฟังก์ชันของคุณเป็นหมายเลขอ้างอิง (เช่นการเรียกกลับ) จากนั้นส่งข้อความ / เรียกใช้ฟังก์ชันเพื่อทำงานหรือประมวลผล ตอนนี้หลังจากการประมวลผลเสร็จสิ้นฟังก์ชั่นที่เรียกว่าจะเรียกฟังก์ชั่นที่ลงทะเบียนของเรา (เช่นตอนนี้โทรกลับเสร็จแล้ว) จึงแสดงให้เราดำเนินการประมวลผล ลิงค์วิกิพีเดีย
นี้อธิบายได้ค่อนข้างดี


1

ฟังก์ชั่นการโทรกลับหรือที่เรียกว่าฟังก์ชั่นการสั่งซื้อที่สูงขึ้นเป็นฟังก์ชั่นที่ส่งผ่านไปยังฟังก์ชั่นอื่นเป็นพารามิเตอร์และฟังก์ชั่นการโทรกลับถูกเรียก (หรือดำเนินการ) ภายในฟังก์ชั่นหลัก

$("#button_1").click(function() {
  alert("button 1 Clicked");
});

ที่นี่เราได้ผ่านฟังก์ชั่นเป็นพารามิเตอร์ไปยังวิธีการคลิก และวิธีการคลิกจะโทร (หรือดำเนินการ) ฟังก์ชั่นการโทรกลับที่เราส่งผ่านไป


1
ฟังก์ชันการเรียกกลับไม่ใช่ฟังก์ชันลำดับที่สูงกว่า มันถูกส่งผ่านไปยังฟังก์ชันลำดับสูงกว่า
danio

1

ฟังก์ชั่นการโทรกลับฟังก์ชั่ นที่ส่งผ่านไปยังฟังก์ชั่นอื่นเป็นอาร์กิวเมนต์

function test_function(){       
 alert("Hello world");  
} 

setTimeout(test_function, 2000);

หมายเหตุ:ในตัวอย่างข้างต้น test_function ที่ใช้เป็นอาร์กิวเมนต์สำหรับฟังก์ชั่น setTimeout


1
ยินดีต้อนรับสู่ Stack Overflow! ก่อนที่จะตอบคำถามให้อ่านคำตอบที่มีอยู่เสมอ คำตอบนี้มีให้แล้ว แทนที่จะทำซ้ำคำตอบให้โหวตคำตอบที่มีอยู่ หลักเกณฑ์บางประการสำหรับการเขียนคำตอบที่ดีสามารถพบได้ที่นี่
dferenc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.