JavaScript แกง: การใช้งานจริงคืออะไร?


172

ฉันคิดว่าฉันยังไม่ได้บ่นหรอก ฉันเข้าใจว่ามันทำอะไรและทำอย่างไร ฉันไม่สามารถนึกถึงสถานการณ์ที่ฉันจะใช้มันได้

คุณใช้ currying ใน JavaScript อยู่ที่ไหน (หรือใช้ห้องสมุดหลักอยู่ที่ไหน) ยินดีต้อนรับสู่การจัดการ DOM หรือตัวอย่างการพัฒนาแอปพลิเคชันทั่วไป

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

มีข้อ จำกัด ในการใช้งานหรือไม่?

ตามที่ร้องขอนี่เป็นแหล่งข้อมูลที่ดีเกี่ยวกับการแก้ปัญหา JavaScript:

ฉันจะเพิ่มมากขึ้นเมื่อพวกเขาปลูกฝังในความคิดเห็น


ดังนั้นตามคำตอบการประยุกต์ใช้การแกงและบางส่วนโดยทั่วไปเป็นเทคนิคความสะดวกสบาย

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


คุณสามารถเพิ่มลิงค์ไปยังทรัพยากรที่อธิบายว่า JS currying คืออะไร? การสอนหรือโพสต์บล็อกจะดีมาก
Eric Schoonover

2
svendtofte.com เป็น longwinded แต่ถ้าคุณข้ามส่วนทั้งหมดจาก "A crash course ใน ML" และเริ่มต้นอีกครั้งที่ "วิธีการเขียน JavaScript curated" มันจะเป็นการแนะนำที่ยอดเยี่ยมสำหรับการแกงใน js
danio

1
นี่เป็นจุดเริ่มต้นที่ดีในการทำความเข้าใจกับแอปพลิเคชั่นแกงและบางส่วน: slid.es/gsklee/functional-programming-in-5-minutes
gsklee

1
ลิงก์ไปยังsvendtofte.comหน้าตาจะตาย - พบได้ในเครื่อง WayBack ผ่านweb.archive.org/web/20130616230053/http://www.svendtofte.com/ขออภัยขออภัยblog.morrisjohns.com/javascript_closures_for_dummiesดูเหมือนว่าจะลง ด้วย
phatskat

1
BTW, รุ่น Resig ของบางส่วนขาด (แน่นอนไม่ได้ "เงิน") ในการที่จะมีแนวโน้มที่จะล้มเหลวถ้าหนึ่งของการ pre-initialised ( "แกงกะหรี่") ข้อโต้แย้งที่จะได้รับค่าไม่ได้กำหนด ใครก็ตามที่สนใจในฟังก์ชั่นการแก้ปัญหาที่ดีควรได้รับต้นฉบับจากfuncitonal.jsของ Oliver Steeleเนื่องจากไม่มีปัญหานั้น
RobG

คำตอบ:


35

@ แฮงค์เกย์

ในการตอบสนองต่อความคิดเห็นของ EmbiggensTheMind:

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

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

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

String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );


6
นี่เป็นคำตอบที่ไม่ดีจริงๆ การแกงไม่มีส่วนเกี่ยวข้องกับแอปพลิเคชั่นบางส่วน การดัดผมช่วยให้การจัดองค์ประกอบฟังก์ชั่น การจัดองค์ประกอบฟังก์ชั่นช่วยให้ใช้งานฟังก์ชั่น ฟังก์ชั่นการใช้ซ้ำช่วยเพิ่มความสามารถในการบำรุงรักษาโค้ด มันง่ายมาก!

2
@ ท่านที่รักคุณเป็นคำตอบที่แย่มาก เห็นได้ชัดว่าการแกงจะทำให้ฟังก์ชั่นอร่อยยิ่งขึ้น คุณพลาดจุดนี้ไปอย่างชัดเจน
Callat

112

นี่คือการใช้งานที่น่าสนใจและการปฏิบัติของ currying ใน JavaScript ที่ใช้ปิด :

function converter(toUnit, factor, offset, input) {
    offset = offset || 0;
    return [((offset + input) * factor).toFixed(2), toUnit].join(" ");
}

var milesToKm = converter.curry('km', 1.60936, undefined);
var poundsToKg = converter.curry('kg', 0.45460, undefined);
var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32);

milesToKm(10);            // returns "16.09 km"
poundsToKg(2.5);          // returns "1.14 kg"
farenheitToCelsius(98);   // returns "36.67 degrees C"

สิ่งนี้ขึ้นอยู่กับcurryส่วนขยายของFunctionแม้ว่าคุณจะเห็นว่ามันใช้งานได้เท่านั้นapply(ไม่มีอะไรแฟนซีเกินไป):

Function.prototype.curry = function() {
    if (arguments.length < 1) {
        return this; //nothing to curry with - return function
    }
    var __method = this;
    var args = toArray(arguments);
    return function() {
        return __method.apply(this, args.concat([].slice.apply(null, arguments)));
    }
}

5
มันเยี่ยมมาก! ฉันเห็นมันคล้ายกับข้อความเสียงกระเพื่อมที่ระบุว่า "เสียงกระเพื่อมเป็นภาษาโปรแกรมได้"
santiagobasulto

2
น่าสนใจ แต่ตัวอย่างนี้ใช้งานไม่ได้ offset+inputจะเป็นตัวอย่างundefined + 1.60936ของคุณ milesToKmผลลัพธ์NaNนั้น
นาธานลอง

3
@Nathan - ไม่สามารถกำหนด offset ได้ - จะมีค่าเริ่มต้นเป็น 0
AngusC

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

11
สามารถทำได้ด้วยวิธี ES5 bind () ผูกสร้างฟังก์ชั่นใหม่ที่เมื่อเรียกเรียกฟังก์ชั่นเดิมที่มีบริบทของการโต้แย้งครั้งแรกและมีลำดับของการขัดแย้งที่ตามมา (ก่อนหน้าใด ๆ ผ่านไปยังฟังก์ชั่นใหม่) ดังนั้นคุณสามารถทำได้ ... var milesToKm = converter.bind (นี่, 'km', 1.60936); หรือ var farenheitToCelsius = converter.bind (นี่คือ 'degrees C', 0.5556, -32); อาร์กิวเมนต์แรกบริบทนี้ไม่เกี่ยวข้องที่นี่เพื่อให้คุณสามารถผ่านการไม่ได้กำหนด แน่นอนว่าคุณจะต้องเพิ่มต้นแบบฟังก์ชันพื้นฐานด้วยวิธีการผูกของคุณเองสำหรับทางเลือก ES5 ที่ไม่ใช่ทางเลือก
hacklikecrack

7

ฉันพบฟังก์ชั่นที่คล้ายกับ python functools.partialมีประโยชน์มากกว่าใน JavaScript

function partial(fn) {
  return partialWithScope.apply(this,
    Array.prototype.concat.apply([fn, this],
      Array.prototype.slice.call(arguments, 1)));
}

function partialWithScope(fn, scope) {
  var args = Array.prototype.slice.call(arguments, 2);
  return function() {
    return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
  };
}

ทำไมคุณต้องการใช้ สถานการณ์ทั่วไปที่คุณต้องการใช้นี่คือเมื่อคุณต้องการผูกthisในฟังก์ชั่นเป็นค่า:

var callback = partialWithScope(Object.function, obj);

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

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


7

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

var converter = function(ratio, symbol, input) {
    return (input*ratio).toFixed(2) + " " + symbol;
}

var kilosToPoundsRatio = 2.2;
var litersToUKPintsRatio = 1.75;
var litersToUSPintsRatio = 1.98;
var milesToKilometersRatio = 1.62;

converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs
converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints
converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints
converter(milesToKilometersRatio, "km", 34); //55.08 km

ฉันหวังว่า Douglas Crockford ใน "JavaScript: The Good Parts" ได้กล่าวถึงประวัติความเป็นมาและการใช้งานแกงอย่างแท้จริงมากกว่าที่จะพูด เป็นเวลานานหลังจากที่อ่านสิ่งนั้นฉันรู้สึกตัวจนกระทั้งฉันกำลังศึกษาการเขียนโปรแกรมฟังก์ชั่นและตระหนักว่ามันมาจากไหน

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


2
รหัสของคุณเข้าใจได้ง่ายกว่า Prisoner Zero และมันแก้ปัญหาเดียวกันได้โดยไม่ต้องแก้ปัญหาหรือซับซ้อนอะไร คุณมี 2 นิ้วโป้งขึ้นและเขามีเกือบ 100 รูปที่ไป
DR01D

2

มันไม่มีความมหัศจรรย์หรืออะไรเลย ... เป็นเพียงชวเลขที่น่ารื่นรมย์สำหรับฟังก์ชั่นที่ไม่ระบุชื่อ

partial(alert, "FOO!") เทียบเท่ากับ function(){alert("FOO!");}

partial(Math.max, 0) สอดคล้องกับ function(x){return Math.max(0, x);}

การเรียกไปที่บางส่วน ( คำศัพท์MochiKitฉันคิดว่าห้องสมุดอื่น ๆ ให้ฟังก์ชั่นวิธีการ. ซึ่งทำสิ่งเดียวกัน) ดูดีขึ้นเล็กน้อยและมีเสียงดังน้อยกว่าฟังก์ชั่นที่ไม่ระบุชื่อ


1

ในฐานะที่เป็นสำหรับห้องสมุดที่ใช้มันมีเสมอฟังก์ชั่น

เมื่อไหร่จะมีประโยชน์ใน JS? อาจเป็นเวลาเดียวกันกับที่มันมีประโยชน์ในภาษาสมัยใหม่อื่น ๆ แต่ครั้งเดียวที่ฉันเห็นว่าตัวเองกำลังใช้มันอยู่ร่วมกับแอปพลิเคชั่นบางส่วน


ขอบคุณ Hank - โปรดช่วยขยายต่อเมื่อมันมีประโยชน์โดยทั่วไปไหม?
เดฟโนแลน

1

ฉันจะบอกว่าส่วนใหญ่ห้องสมุดภาพเคลื่อนไหวทั้งหมดใน JS กำลังใช้การแกง แทนที่จะต้องผ่านแต่ละชุดขององค์ประกอบที่ได้รับผลกระทบและฟังก์ชั่นอธิบายว่าองค์ประกอบควรทำหน้าที่อย่างไรกับฟังก์ชั่นการสั่งซื้อที่สูงขึ้นซึ่งจะช่วยให้มั่นใจได้ว่าทุกเวลาจะง่ายขึ้นสำหรับลูกค้าที่จะเผยแพร่ ฟังก์ชั่นเช่น "slideUp", "fadeIn" ที่ใช้องค์ประกอบเป็นอาร์กิวเมนต์เท่านั้นและนั่นเป็นเพียงบางส่วนของฟังก์ชั่น curried ที่ส่งคืนฟังก์ชันลำดับสูงด้วยฟังก์ชัน "ภาพเคลื่อนไหว" เริ่มต้นในตัว


เหตุใดจึงดีกว่าที่จะแกงกะหรี่ฟังก์ชั่นที่สูงกว่าแทนที่จะเรียกมันว่าค่าเริ่มต้น
เดฟโนแลน

1
เพราะมันเป็นมอดุลาร์สูงกว่ามากที่จะสามารถ "doMathOperation" ด้วยการเพิ่ม / การคูณ / สแควร์ / โมดูลัส / การสอบเทียบอื่น ๆ ที่ต้องการมากกว่าที่จะจินตนาการว่า "เริ่มต้น" ทั้งหมดที่ฟังก์ชั่นที่สูงกว่าสามารถรองรับได้
gizmo

1

นี่คือตัวอย่าง

ฉันกำลังสร้างกลุ่มของฟิลด์ด้วย JQuery ดังนั้นฉันจึงสามารถดูได้ว่าผู้ใช้ทำอะไรอยู่ รหัสมีลักษณะดังนี้:

$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);

(สำหรับผู้ใช้ที่ไม่ใช่ JQuery ฉันกำลังบอกว่าทุกครั้งที่สองสามฟิลด์ได้รับหรือโฟกัสฉันต้องการให้เรียกใช้ฟังก์ชัน trackActivity () ฉันสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อได้ แต่ฉันต้องทำซ้ำ 4 ครั้งดังนั้นฉันดึงมันออกมาแล้วตั้งชื่อ)

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


1

ฟังก์ชัน JavaScript เรียกว่า lamda ในภาษาที่ใช้งานอื่น มันสามารถใช้ในการเขียน api ใหม่ (ฟังก์ชั่นที่มีประสิทธิภาพหรือซับซ้อน) ขึ้นอยู่กับการป้อนข้อมูลที่เรียบง่ายของนักพัฒนาคนอื่น แกงเป็นเพียงหนึ่งในเทคนิค คุณสามารถใช้มันเพื่อสร้าง API ที่ง่ายขึ้นเพื่อเรียก API ที่ซับซ้อน หากคุณเป็นผู้พัฒนาที่ใช้ API แบบง่าย (ตัวอย่างเช่นคุณใช้ jQuery เพื่อทำการจัดการอย่างง่าย) คุณไม่จำเป็นต้องใช้แกง แต่ถ้าคุณต้องการสร้าง API ที่ง่ายขึ้น Curry ก็คือเพื่อนของคุณ คุณต้องเขียนเฟรมเวิร์ก javascript (เช่น jQuery, mootools) หรือไลบรารี่จากนั้นคุณสามารถชื่นชมพลังของมัน ฉันเขียนฟังก์ชันการปรับปรุงแกงที่http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html. คุณไม่จำเป็นต้องใช้วิธีการแกงเพื่อทำการแกง แต่ช่วยในการทำแกง แต่คุณสามารถทำได้ด้วยตนเองโดยการเขียนฟังก์ชัน A () {} เพื่อส่งกลับฟังก์ชัน B อื่น () {} เพื่อให้น่าสนใจยิ่งขึ้นให้ใช้ฟังก์ชัน B () เพื่อส่งกลับฟังก์ชันอื่น C ()


1

ฉันรู้ว่ามันเป็นด้ายเก่า แต่ฉันจะต้องแสดงให้เห็นว่ามีการใช้สิ่งนี้ในไลบรารี javascript อย่างไร

ฉันจะใช้ห้องสมุด lodash.js เพื่ออธิบายแนวคิดเหล่านี้อย่างเป็นรูปธรรม

ตัวอย่าง:

var fn = function(a,b,c){ 
return a+b+c+(this.greet || '); 
}

แอพลิเคชันบางส่วน:

var partialFnA = _.partial(fn, 1,3);

ความดีความชอบ:

var curriedFn = _.curry(fn);

ผูกพัน:

var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}

การใช้งาน:

curriedFn(1)(3)(5); // gives 9 
or 
curriedFn(1,3)(5); // gives 9 
or 
curriedFn(1)(_,3)(2); //gives 9


partialFnA(5); //gives 9

boundFn(5); //gives 9!

ความแตกต่าง:

หลังจากการแก้ปัญหาเราได้รับฟังก์ชั่นใหม่โดยไม่มีพารามิเตอร์ผูกไว้ล่วงหน้า

หลังจากแอปพลิเคชั่นบางส่วนเราได้รับฟังก์ชั่นที่ถูกผูกไว้กับพารามิเตอร์บางอัน

ในการผูกเราสามารถผูกบริบทที่จะใช้ในการแทนที่ 'นี้' ถ้าไม่ผูกพันเริ่มต้นของฟังก์ชั่นใด ๆ จะเป็นขอบเขตหน้าต่าง

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


0

ฉันยอมรับว่าบางครั้งคุณต้องการให้ลูกบอลกลิ้งโดยการสร้างฟังก์ชันหลอกที่มักจะมีค่าของอาร์กิวเมนต์แรกที่กรอกข้อมูลโชคดีฉันเจอไลบรารี JavaScript ใหม่ที่เรียกว่า jPaq (h ttp: // jpaq.org/ ) ซึ่งมีฟังก์ชันนี้ สิ่งที่ดีที่สุดเกี่ยวกับไลบรารี่คือความจริงที่ว่าคุณสามารถดาวน์โหลดบิลด์ของคุณเองซึ่งมีเฉพาะโค้ดที่คุณต้องการ



0

แค่ต้องการเพิ่มแหล่งข้อมูลสำหรับ Functional.js:

การบรรยาย / การประชุมอธิบายแอปพลิเคชันบางอย่าง http://www.youtube.com/watch?v=HAcN3JyQoyY

อัปเดตห้องสมุด Functional.js: https://github.com/loop-recur/FunctionalJS ผู้ช่วยที่ดี (ขออภัยใหม่ที่นี่ไม่มีชื่อเสียง: p): / loop-recur / PreludeJS

เมื่อเร็ว ๆ นี้ฉันใช้ห้องสมุดนี้มากเพื่อลดการซ้ำซ้อนในไลบรารีผู้ช่วยลูกค้า js IRC มันเป็นสิ่งที่ยอดเยี่ยม - ช่วยล้างและทำให้โค้ดง่ายขึ้น

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


0

คุณสามารถใช้การเชื่อมเนทีฟสำหรับโซลูชันบรรทัดเดียวที่รวดเร็ว

function clampAngle(min, max, angle) {
    var result, delta;
    delta = max - min;
    result = (angle - min) % delta;
    if (result < 0) {
        result += delta;
    }
    return min + result;
};

var clamp0To360 = clampAngle.bind(null, 0, 360);

console.log(clamp0To360(405)) // 45


0

แทงอีกอันจากการทำงานกับสัญญา

(ข้อจำกัดความรับผิดชอบ: JS noob มาจากโลก Python แม้จะมีการแกงไม่ได้ใช้มากนัก แต่มันก็มีประโยชน์ในบางโอกาสดังนั้นฉันจึงเปลฟังฟังก์ชั่นการแกง - ดูลิงก์)

ก่อนอื่นฉันเริ่มด้วย ajax call ฉันมีบางอย่างในการประมวลผลที่จะทำในความสำเร็จ แต่ในความล้มเหลวผมเพียงต้องการที่จะให้ข้อเสนอแนะของผู้ใช้ที่เรียกสิ่งที่ส่งผลให้เกิดข้อผิดพลาดบาง ในรหัสจริงของฉันฉันแสดงความคิดเห็นข้อผิดพลาดในแผงบูต แต่เพียงแค่ใช้การเข้าสู่ระบบที่นี่

ฉันแก้ไข URL สดของฉันเพื่อทำให้สิ่งนี้ล้มเหลว

function ajax_batch(e){
    var url = $(e.target).data("url");

    //induce error
    url = "x" + url;

    var promise_details = $.ajax(
        url,
        {
            headers: { Accept : "application/json" },
            // accepts : "application/json",
            beforeSend: function (request) {
                if (!this.crossDomain) {
                    request.setRequestHeader("X-CSRFToken", csrf_token);
                }
        },
        dataType : "json",
        type : "POST"}
    );
    promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}

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

ฉันยังคงมีข้อมูลที่มีอยู่ในเวลาการเข้ารหัสเท่านั้น - ในกรณีของฉันฉันมีจำนวนแบตช์ที่เป็นไปได้ แต่ฉันไม่รู้ว่าอันไหนที่ล้มเหลวในการแยกวิเคราะห์การตอบสนองของเซิร์ฟเวอร์เกี่ยวกับ URL ที่ล้มเหลว

function fail_status_specific_to_batch(d){
    console.log("bad batch run, dude");
    console.log("response.status:" + d.status);
}

มาทำกันเถอะ เอาต์พุตคอนโซลคือ:

คอนโซล:

bad batch run, dude utility.js (line 109) response.status:404

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

    ... rest is as before...
    var target = $(e.target).text();
    var context = {"user_msg": "bad batch run, dude.  you were calling :" + target};
    var contexted_fail_notification = curry(generic_fail, context); 

    promise_details.then(notify_batch_success, contexted_fail_notification);
}

function generic_fail(context, d){
    console.log(context);
    console.log("response.status:" + d.status);
}

function curry(fn) {
     var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
     return function () {
        var new_args = slice.call(arguments),
              args = stored_args.concat(new_args);
        return fn.apply(null, args);
     };
}

คอนโซล:

Object { user_msg="bad batch run, dude. you were calling :Run ACL now"} utility.js (line 117) response.status:404 utility.js (line 118)

โดยทั่วไปเมื่อพิจารณาว่ามีการใช้งานการโทรกลับจำนวนมากใน JS การแก้ปัญหาดูเหมือนจะเป็นเครื่องมือที่มีประโยชน์มาก

https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/ http://www.drdobbs.com/open-source/currying-and-partial-functions-in- javasc / 231001821? pgno = 2

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