حساب
calc هي وظيفة غير متزامنة نريد إجراء تحليل (تحليل الأداء). حسب الاتفاقية ، معلمة آخرها هي callback . نستخدم calc مثل هذا:
calc (arg ، (err ، res) => console.log (err || res))
ربما تكون أسهل طريقة لتحليل الأداء على وظيفة مثل calc هي إضافة منطق توقيت إلى حيث نحتاج إلى تحليل:
const t0 = date.now () calc (arg ، (err ، res) => {const t1 = date.now () console.log (`log: time: $ {t1 = t0}`) console.log (err || res)}) ومع ذلك ، هذا ليس حلًا قابلاً لإعادة الاستخدام. في كل مرة نرغب فيها في الوقت ، يتعين علينا تقديم T0 في النطاق الخارجي وتغيير callback لقياس الوقت وتسجيله.
الطريقة المثالية بالنسبة لي هي أن أكون قادرًا على الوقت فقط عن طريق لف وظيفة غير متزامنة:
timeit (calc) (arg ، (err ، res) => console.log (err || res))
يجب أن تكون timeIt قادرًا على إجراء التحليل وتسجيل وقت تنفيذ كل وظيفة غير متزامنة بشكل جيد.
لاحظ أن timeIt(calc) لديه نفس توقيع الوظيفة مثل وظيفة calc الأصلية ، أي أنها تقبل نفس المعلمات وإرجاع نفس القيمة ، بل تضيف فقط ميزة إلى cale (ميزة يمكن تسجيلها).
يمكن استبدال calc و timeit (calc) ببعضهما البعض في أي وقت.
timeIt نفسها هي وظيفة ترتيب أعلى لأنها تقبل وظيفة وإرجاع وظيفة. في مثالنا ، فإنه يقبل وظيفة غير متزامنة Calc وتُرجع وظيفة بنفس المعلمات وقيمة الإرجاع مثل Calc.
ما يلي يوضح كيف ننفذ وظيفة TimeIt:
const timeit = r.curry ((Report ، f) => (... args) => {const t0 = date.now () const nargs = r.init (args) const callback = R.LAS f (... nargs)}) const timeIt1 = timeIt ((t ، err ، res) => console.log (`log: $ {err || res} تم إنتاجها بعد: $ {t}`)) const calc = (x ، y ، z ، callback) => setTimeout () console.log (err || res)) timeit1 (calc) (18 ، 7 ، 3 ، (err ، res) => console.log (err || res))) يقبل تطبيق timeIt معلمتين:
التقرير: يتم استخدام وظيفة لإنشاء نتائج التحليل
F: الوظيفة غير المتزامنة نريد إجراء التحليل
timeIt1 هي وظيفة مريحة وعملية ، فهي تستخدم فقط console.log لتسجيل نتائج قياس الوقت. نحن نحددها عن طريق تمرير معلمة report إلى وظيفة timeIt العامة.
لقد حققنا الهدف ، والآن يمكننا أن نلف الوظيفة غير المتزامنة في timeIt1 والوقت الذي يتم فيه توقيت:
TimeIt1 (calc) (18 ، 7 ، 3 ، (err ، res) => console.log (err || res))
تتلقى وظيفة timeIt العامة وظيفة رد اتصال report ودالة غير متزامنة وإرجاع وظيفة غير متزامنة جديدة. هذه الوظيفة غير المتزامنة لها نفس المعلمات وقيمة الإرجاع مثل الوظيفة الأصلية. يمكننا استخدام هذا:
TimeIt ((الوقت ، ... نتيجة) => // تقرير رد الاتصال: سجل الوقت ، asyncfunc) (المعلمات ... ، (... نتيجة) => // نتيجة دالة Async)
الآن دعنا نغوص في تنفيذ timeIt . يمكننا ببساطة إنشاء وظيفة عامة مثل timeIt1 ، لأن timeIt يتم توضيحه باستخدام R.curry .
لا أخطط لمناقشة coriculization في هذا المنشور ، لكن الكود التالي يوضح الاستخدام الرئيسي للكورريكول:
const f = r.curry ((x ، y) => x + y) f (1 ، 10) // == 11f (1) (10) // == 11const plus1 = f (1) plus1 (10) // == 11
من ناحية أخرى ، هناك العديد من المشكلات التي تم تنفيذها في TimeIt بهذه الطريقة:
(... args) => {const t1 = date.now () رد الاتصال (... args) تقرير (t1 - t0 ، ... args)} هذه وظيفة مجهولة (تُعرف أيضًا باسم Lambda ، رد الاتصال) والتي تسمى بعد تنفيذ الوظيفة الأصلية بشكل غير متزامن. المشكلة الرئيسية هي أن هذه الوظيفة ليس لديها آلية للتعامل مع الاستثناءات. إذا كان callback يلقي استثناءً ، فلن يتم استدعاء report أبدًا.
يمكننا إضافة try / catch وظيفة lambda هذه ، ولكن جذر المشكلة هو أن callback report هما وظيفتان void ، ولا يرتبطان. timeIt يحتوي على اثنين من الاستمرارية ( report ورد callback ). إذا قمنا فقط بتسجيل وقت التنفيذ ضمن console أو إذا كنا متأكدين من أن أي report أو callback سوف يرمي استثناءات ، فكل شيء على ما يرام. ولكن إذا أردنا إجراء بعض السلوك بناءً على نتائج التحليل (ما يسمى بالتوسعة التلقائية) ، فنحن بحاجة إلى تعزيز وتوضيح تسلسل الاستمرار في برنامجنا.
حسنًا ، آمل أن يكون المحتوى الكامل لهذه المقالة مفيدًا لدراسة الجميع وعمله. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل.