From c01f0f4d6fb014b1bfeeda20ab448c7c3a1874e1 Mon Sep 17 00:00:00 2001 From: salah elhossiny Date: Tue, 2 Jun 2020 19:40:00 +0200 Subject: [PATCH] error handling with promises - promisification - microtasks --- .../01-error-async/solution.md | 6 +- .../01-error-async/task.md | 4 +- .../04-promise-error-handling/article.md | 76 +++++++++---------- 1-js/11-async/06-promisify/article.md | 36 ++++----- 1-js/11-async/07-microtask-queue/article.md | 71 +++++++++-------- 5 files changed, 96 insertions(+), 97 deletions(-) diff --git a/1-js/11-async/04-promise-error-handling/01-error-async/solution.md b/1-js/11-async/04-promise-error-handling/01-error-async/solution.md index 0d43f55e0..fdfc04e5c 100644 --- a/1-js/11-async/04-promise-error-handling/01-error-async/solution.md +++ b/1-js/11-async/04-promise-error-handling/01-error-async/solution.md @@ -1,4 +1,4 @@ -The answer is: **no, it won't**: +الإجابة هي **no, it won't**: ```js run new Promise(function(resolve, reject) { @@ -8,6 +8,6 @@ new Promise(function(resolve, reject) { }).catch(alert); ``` -As said in the chapter, there's an "implicit `try..catch`" around the function code. So all synchronous errors are handled. +كما ذكر في الفصل ، هناك "try...catch" ضمنية حول رمز الوظيفة. لذلك يتم التعامل مع جميع الأخطاء المتزامنة. -But here the error is generated not while the executor is running, but later. So the promise can't handle it. +ولكن هنا يتم إنشاء الخطأ ليس أثناء تشغيل المنفذ ، ولكن في وقت لاحق. لذا الوعد لا يمكن أن ينفذ به. diff --git a/1-js/11-async/04-promise-error-handling/01-error-async/task.md b/1-js/11-async/04-promise-error-handling/01-error-async/task.md index bafc47ce9..194571713 100644 --- a/1-js/11-async/04-promise-error-handling/01-error-async/task.md +++ b/1-js/11-async/04-promise-error-handling/01-error-async/task.md @@ -1,6 +1,6 @@ -# Error in setTimeout +# خطأ في setTimeout -What do you think? Will the `.catch` trigger? Explain your answer. +ما رأيك؟ هل سيتم تشغيل "catch"؟ اشرح اجابتك. ```js new Promise(function(resolve, reject) { diff --git a/1-js/11-async/04-promise-error-handling/article.md b/1-js/11-async/04-promise-error-handling/article.md index 7c6af6a33..a3425ab7c 100644 --- a/1-js/11-async/04-promise-error-handling/article.md +++ b/1-js/11-async/04-promise-error-handling/article.md @@ -1,9 +1,9 @@ -# Error handling with promises +# التعامل مع الأخطاء في الـ `promises` -Promise chains are great at error handling. When a promise rejects, the control jumps to the closest rejection handler. That's very convenient in practice. +سلاسل الـ `promises` رائعة في معالجة الأخطاء. عندما يرفض الوعد ، يقفز عنصر التحكم إلى أقرب معالج رفض. هذا مريح للغاية في الممارسة. -For instance, in the code below the URL to `fetch` is wrong (no such site) and `.catch` handles the error: +على سبيل المثال ، في التعليمات البرمجية أسفل عنوان URL لـ `جلب 'غير صحيح (لا يوجد مثل هذا الموقع) ويتعامل` .atch' مع الخطأ: ```js run *!* @@ -13,9 +13,9 @@ fetch('https://no-such-server.blabla') // rejects .catch(err => alert(err)) // TypeError: failed to fetch (the text may vary) ``` -As you can see, the `.catch` doesn't have to be immediate. It may appear after one or maybe several `.then`. +كما ترى ، لا يجب أن يكون "الصيد" فوريًا. قد تظهر بعد واحد أو ربما عدة "ثم". -Or, maybe, everything is all right with the site, but the response is not valid JSON. The easiest way to catch all errors is to append `.catch` to the end of chain: +أو ، ربما ، كل شيء على ما يرام مع الموقع ، ولكن الإجابة غير صالحة لـ JSON. أسهل طريقة للقبض على جميع الأخطاء هي إلحاق ".catch" بنهاية السلسلة: ```js run fetch('/article/promise-chaining/user.json') @@ -38,13 +38,13 @@ fetch('/article/promise-chaining/user.json') */!* ``` -Normally, such `.catch` doesn't trigger at all. But if any of the promises above rejects (a network problem or invalid json or whatever), then it would catch it. +عادةً ، لا يتم تشغيل ".catch" على الإطلاق. ولكن إذا رفض أي من الوعود أعلاه (مشكلة في الشبكة أو json غير صالح أو أيا كان) ، فسوف يلتقطها. ## Implicit try..catch -The code of a promise executor and promise handlers has an "invisible `try..catch`" around it. If an exception happens, it gets caught and treated as a rejection. +رمز تنفيذ الوعد ومعالجو الوعد يحتوي على "محاولة غير مرئية" غير مرئية حوله. إذا حدث استثناء ، يتم القبض عليه ومعاملته على أنه رفض. -For instance, this code: +على سبيل المثال ، هذا الكود: ```js run new Promise((resolve, reject) => { @@ -54,7 +54,7 @@ new Promise((resolve, reject) => { }).catch(alert); // Error: Whoops! ``` -...Works exactly the same as this: +... يعمل تمامًا مثل هذا: ```js run new Promise((resolve, reject) => { @@ -64,11 +64,11 @@ new Promise((resolve, reject) => { }).catch(alert); // Error: Whoops! ``` -The "invisible `try..catch`" around the executor automatically catches the error and turns it into rejected promise. +الـ `try..catch` غير المرئية حول المنفذ تقوم بالتقاط الحطأ بشكل أوتوماتيكي ويحوله إلى `rejected promise`. -This happens not only in the executor function, but in its handlers as well. If we `throw` inside a `.then` handler, that means a rejected promise, so the control jumps to the nearest error handler. +يحدث هذا ليس فقط في وظيفة المنفذ ، ولكن في معالجاتها أيضًا. إذا قمنا "بإلقاء" داخل معالج ".then" ، فهذا يعني وعدًا مرفوضًا ، لذلك ينتقل عنصر التحكم إلى أقرب معالج أخطاء. -Here's an example: +إليك مثال: ```js run new Promise((resolve, reject) => { @@ -80,7 +80,7 @@ new Promise((resolve, reject) => { }).catch(alert); // Error: Whoops! ``` -This happens for all errors, not just those caused by the `throw` statement. For example, a programming error: +يحدث هذا لجميع الأخطاء ، وليس فقط تلك التي تسببها عبارة `throw`. على سبيل المثال ، خطأ في البرمجة: ```js run new Promise((resolve, reject) => { @@ -92,17 +92,17 @@ new Promise((resolve, reject) => { }).catch(alert); // ReferenceError: blabla is not defined ``` -The final `.catch` not only catches explicit rejections, but also accidental errors in the handlers above. +لا يكتفي "catch" النهائي برفض صريح فحسب ، بل يشتمل أيضًا على أخطاء عرضية في المعالجات أعلاه. -## Rethrowing +## إعادة رمي الخطأ -As we already noticed, `.catch` at the end of the chain is similar to `try..catch`. We may have as many `.then` handlers as we want, and then use a single `.catch` at the end to handle errors in all of them. +كما لاحظنا بالفعل ، ".catch" في نهاية السلسلة يشبه "try..catch". قد يكون لدينا العدد الذي تريده من معالجات "then`" ، ثم نستخدم ".catch" واحدًا في النهاية للتعامل مع الأخطاء في جميعها. -In a regular `try..catch` we can analyze the error and maybe rethrow it if it can't be handled. The same thing is possible for promises. +في "المحاولة .. المصيد" العادية ، يمكننا تحليل الخطأ وربما إعادة ترميمه إذا لم يكن من الممكن معالجته. نفس الشيء ممكن للوعود. -If we `throw` inside `.catch`, then the control goes to the next closest error handler. And if we handle the error and finish normally, then it continues to the next closest successful `.then` handler. +إذا قمنا `بإلقاء` داخل` .catch` ، فسينتقل عنصر التحكم إلى أقرب معالج أخطاء التالي. وإذا تعاملنا مع الخطأ وانتهينا بشكل طبيعي ، فسيستمر إلى أقرب معالج `.then` التالي. -In the example below the `.catch` successfully handles the error: +في المثال أدناه يتعامل `catch` بنجاح مع الخطأ: ```js run // the execution: catch -> then @@ -117,9 +117,9 @@ new Promise((resolve, reject) => { }).then(() => alert("Next successful handler runs")); ``` -Here the `.catch` block finishes normally. So the next successful `.then` handler is called. +هنا تنتهي كتلة "الصيد" بشكل طبيعي. لذلك يتم استدعاء معالج ".then" الناجح التالي. -In the example below we see the other situation with `.catch`. The handler `(*)` catches the error and just can't handle it (e.g. it only knows how to handle `URIError`), so it throws it again: +في المثال أدناه نرى الموقف الآخر مع ".catch". معالج `(*)` يمسك الخطأ ولا يمكنه التعامل معه (على سبيل المثال ، فهو يعرف فقط كيفية التعامل مع `URIError`) ، لذا فإنه يرميه مرة أخرى: ```js run // the execution: catch -> catch -> then @@ -149,11 +149,11 @@ new Promise((resolve, reject) => { }); ``` -The execution jumps from the first `.catch` `(*)` to the next one `(**)` down the chain. +يقفز التنفيذ من أول ".catch" `(*)` إلى التالي `(**)` أسفل السلسلة. -## Unhandled rejections +## حالات الرفض التي لم تتم معالجتها -What happens when an error is not handled? For instance, we forgot to append `.catch` to the end of the chain, like here: +ماذا يحدث عندما لا يتم معالجة الخطأ؟ على سبيل المثال ، نسينا إلحاق "الصيد" بنهاية السلسلة ، كما يلي: ```js untrusted run refresh new Promise(function() { @@ -164,15 +164,15 @@ new Promise(function() { }); // without .catch at the end! ``` -In case of an error, the promise becomes rejected, and the execution should jump to the closest rejection handler. But there is none. So the error gets "stuck". There's no code to handle it. +Iفي حالة وجود خطأ ، يصبح الوعد مرفوضًا ، ويجب أن يقفز التنفيذ إلى أقرب معالج رفض. ولكن لا يوجد شيء. لذلك "عالق" الخطأ. لا يوجد رمز للتعامل معها. -In practice, just like with regular unhandled errors in code, it means that something has gone terribly wrong. +من الناحية العملية ، تمامًا كما هو الحال مع الأخطاء العادية التي لم تتم معالجتها في التعليمات البرمجية ، فهذا يعني أن شيئًا ما قد حدث خطأ فادحًا. -What happens when a regular error occurs and is not caught by `try..catch`? The script dies with a message in the console. A similar thing happens with unhandled promise rejections. +ماذا يحدث عند حدوث خطأ عادي ولا يتم اكتشافه بواسطة "try..catch"؟ يموت البرنامج النصي مع رسالة في وحدة التحكم. يحدث شيء مماثل مع رفض الوعد غير المعالج. -The JavaScript engine tracks such rejections and generates a global error in that case. You can see it in the console if you run the example above. +يتتبع محرك جافا سكريبت حالات الرفض هذه ويولد خطأً عامًا في هذه الحالة. يمكنك رؤيته في وحدة التحكم إذا قمت بتشغيل المثال أعلاه. -In the browser we can catch such errors using the event `unhandledrejection`: +في المتصفح يمكننا اكتشاف مثل هذه الأخطاء باستخدام الحدث `unhandledrejection`: ```js run *!* @@ -188,17 +188,17 @@ new Promise(function() { }); // no catch to handle the error ``` -The event is the part of the [HTML standard](https://html.spec.whatwg.org/multipage/webappapis.html#unhandled-promise-rejections). +الحدث هو جزء من [معيار HTML] (https://html.spec.whatwg.org/multipage/webappapis.html#unhandled-promise-rejections). -If an error occurs, and there's no `.catch`, the `unhandledrejection` handler triggers, and gets the `event` object with the information about the error, so we can do something. +إذا حدث خطأ ، ولم يكن هناك "التقاط" ، فسيتم تشغيل معالج "unhandledrejection" ، ويحصل على كائن "الحدث" مع معلومات حول الخطأ ، حتى نتمكن من القيام بشيء ما. -Usually such errors are unrecoverable, so our best way out is to inform the user about the problem and probably report the incident to the server. +عادة ما تكون مثل هذه الأخطاء غير قابلة للاسترداد ، لذلك أفضل طريقة للخروج هي إبلاغ المستخدم بالمشكلة وربما الإبلاغ عن الحادث إلى الخادم. -In non-browser environments like Node.js there are other ways to track unhandled errors. +في البيئات غير المستعرضة مثل Node.js ، هناك طرق أخرى لتتبع الأخطاء التي لم تتم معالجتها. -## Summary +## ملخص -- `.catch` handles errors in promises of all kinds: be it a `reject()` call, or an error thrown in a handler. -- We should place `.catch` exactly in places where we want to handle errors and know how to handle them. The handler should analyze errors (custom error classes help) and rethrow unknown ones (maybe they are programming mistakes). -- It's ok not to use `.catch` at all, if there's no way to recover from an error. -- In any case we should have the `unhandledrejection` event handler (for browsers, and analogs for other environments) to track unhandled errors and inform the user (and probably our server) about them, so that our app never "just dies". +- يعالج `.catch` الأخطاء في الوعود بجميع أنواعها: سواء كان استدعاء` `رفض ()` أو خطأ تم طرحه في معالج. +- يجب وضع ".catch" بالضبط في الأماكن التي نرغب في معالجة الأخطاء فيها ومعرفة كيفية التعامل معها. يجب أن يقوم المعالج بتحليل الأخطاء (تساعد فئات الأخطاء المخصصة) وإعادة إنشاء الأخطاء غير المعروفة (ربما تكون أخطاء برمجة). +- لا بأس بعدم استخدام "الصيد" على الإطلاق ، إذا لم تكن هناك طريقة للتعافي من خطأ. +- على أي حال ، يجب أن يكون لدينا معالج الأحداث `unhandledrejection` (للمتصفحات والنظير للبيئات الأخرى) لتتبع الأخطاء التي لم تتم معالجتها وإبلاغ المستخدم (وربما خادمنا) بشأنها ، حتى لا يموت تطبيقنا أبدًا. \ No newline at end of file diff --git a/1-js/11-async/06-promisify/article.md b/1-js/11-async/06-promisify/article.md index 4ef622546..7a5d415ae 100644 --- a/1-js/11-async/06-promisify/article.md +++ b/1-js/11-async/06-promisify/article.md @@ -1,10 +1,10 @@ # Promisification -"Promisification" is a long word for a simple transformation. It's the conversion of a function that accepts a callback into a function that returns a promise. +"Promisification" هي كلمة طويلة للتحول البسيط. إنه تحويل دالة تقبل رد الاتصال إلى دالة ترجع promise. -Such transformations are often required in real-life, as many functions and libraries are callback-based. But promises are more convenient, so it makes sense to promisify them. +غالبًا ما تكون هذه التحولات مطلوبة في الحياة الواقعية ، حيث تعتمد العديد من الوظائف والمكتبات على رد الاتصال. لكن الوعود أكثر ملاءمة ، لذلك من المنطقي أن نعدها. -For instance, we have `loadScript(src, callback)` from the chapter . +على سبيل المثال ، لدينا `loadScript (src ، callback)` من الفصل . ```js run function loadScript(src, callback) { @@ -21,7 +21,7 @@ function loadScript(src, callback) { // loadScript('path/script.js', (err, script) => {...}) ``` -Let's promisify it. The new `loadScriptPromise(src)` function achieves the same result, but it accepts only `src` (no `callback`) and returns a promise. +لنحولها إلى promise. تحقق وظيفة `تحميل loadScriptPromise (src)` نفس النتيجة ، لكنها تقبل `src` فقط (لا` رد اتصال`) وتعيد promise. ```js let loadScriptPromise = function(src) { @@ -37,13 +37,13 @@ let loadScriptPromise = function(src) { // loadScriptPromise('path/script.js').then(...) ``` -Now `loadScriptPromise` fits well in promise-based code. +الآن يتلاءم `loadScriptPromise` جيدًا مع التعليمات البرمجية المستندة إلى promises. -As we can see, it delegates all the work to the original `loadScript`, providing its own callback that translates to promise `resolve/reject`. +كما نرى ، فإنه يفوض كل العمل إلى `تحميل` الأصلي `، مما يوفر رد الاتصال الخاص به الذي يترجم إلى الوعد` حل / رفض`. -In practice we'll probably need to promisify many functions, so it makes sense to use a helper. We'll call it `promisify(f)`: it accepts a to-promisify function `f` and returns a wrapper function. +من الناحية العملية ، ربما نحتاج إلى الوعد بالعديد من الوظائف ، لذلك من المنطقي استخدام المساعد. سنطلق عليه `promisify (f)`: يقبل وظيفة to-promisify `f` ويعيد دالة مجمعة. -That wrapper does the same as in the code above: returns a promise and passes the call to the original `f`, tracking the result in a custom callback: +يعمل هذا المجمّع كما هو الحال في الرمز أعلاه: إرجاع وعد وتمرير المكالمة إلى `f` الأصلي ، وتتبع النتيجة في رد اتصال مخصص: ```js function promisify(f) { @@ -69,11 +69,11 @@ let loadScriptPromise = promisify(loadScript); loadScriptPromise(...).then(...); ``` -Here we assume that the original function expects a callback with two arguments `(err, result)`. That's what we encounter most often. Then our custom callback is in exactly the right format, and `promisify` works great for such a case. +هنا نفترض أن الوظيفة الأصلية تتوقع رد اتصال بحججتين `(خطأ ، نتيجة)`. هذا ما نواجهه في أغلب الأحيان. ثم يكون رد الاتصال المخصص الخاص بنا بالتنسيق الصحيح تمامًا ، ويعمل `promisify` بشكل رائع لمثل هذه الحالة. -But what if the original `f` expects a callback with more arguments `callback(err, res1, res2, ...)`? +ولكن ماذا لو توقع `f` الأصلي رد اتصال به المزيد من الوسائط` callback (err ، res1 ، res2 ، ...) `؟ -Here's a more advanced version of `promisify`: if called as `promisify(f, true)`, the promise result will be an array of callback results `[res1, res2, ...]`: +في ما يلي نسخة أكثر تقدمًا من "promisify": إذا تم تسميتها باسم "promisify (f، true)` ، فستكون نتيجة الوعد مجموعة من نتائج الاستدعاء`[res1, res2, ...]`: ```js // promisify(f, true) to get array of results @@ -101,14 +101,14 @@ f = promisify(f, true); f(...).then(arrayOfResults => ..., err => ...) ``` -For more exotic callback formats, like those without `err` at all: `callback(result)`, we can promisify such functions manually without using the helper. +لمزيد من تنسيقات رد الاتصال الغريبة ، مثل تلك التي لا تحتوي على `err` على الإطلاق:` رد الاتصال (النتيجة) `، يمكننا أن نعد هذه الوظائف يدويًا دون استخدام المساعد. -There are also modules with a bit more flexible promisification functions, e.g. [es6-promisify](https://github.com/digitaldesignlabs/es6-promisify). In Node.js, there's a built-in `util.promisify` function for that. +هناك أيضًا وحدات ذات وظائف واعدة أكثر مرونة قليلاً ، على سبيل المثال [es6-promisify] (https://github.com/digitaldesignlabs/es6-promisify). في Node.js ، توجد وظيفة `` use.promisify` مضمنة لذلك. -```smart -Promisification is a great approach, especially when you use `async/await` (see the next chapter), but not a total replacement for callbacks. +`` ذكي +يعد Promisification نهجًا رائعًا ، خاصة عند استخدام `async / await` (انظر الفصل التالي) ، ولكن ليس بديلاً كليًا لعمليات الاسترجاعات. -Remember, a promise may have only one result, but a callback may technically be called many times. +تذكر أن الوعد قد يكون له نتيجة واحدة فقط ، ولكن قد يتم استدعاء الاستدعاء من الناحية الفنية عدة مرات. -So promisification is only meant for functions that call the callback once. Further calls will be ignored. -``` +لذا فإن Promisification مخصص فقط للوظائف التي تستدعي الاستدعاء مرة واحدة. سيتم تجاهل مكالمات أخرى. +`` \ No newline at end of file diff --git a/1-js/11-async/07-microtask-queue/article.md b/1-js/11-async/07-microtask-queue/article.md index 4e01493f0..572a525ad 100644 --- a/1-js/11-async/07-microtask-queue/article.md +++ b/1-js/11-async/07-microtask-queue/article.md @@ -1,11 +1,11 @@ -# Microtasks +# المهام الصغيرة -Promise handlers `.then`/`.catch`/`.finally` are always asynchronous. +Promise معالجات الـ `.then`/`.catch`/`.finally` غير متزامنة دائما -Even when a Promise is immediately resolved, the code on the lines *below* `.then`/`.catch`/`.finally` will still execute before these handlers. +حتى عندما يتم حل promise على الفور ، فإن الكود الموجود على الأسطر * أدناه * `.then` /` .catch` / `.finally` ستستمر قبل تنفيذ هذه المعالجات. -Here's a demo: +هنا عرض توضيحي: ```js run let promise = Promise.resolve(); @@ -15,34 +15,33 @@ promise.then(() => alert("promise done!")); alert("code finished"); // this alert shows first ``` -If you run it, you see `code finished` first, and then `promise done!`. +إذا قمت بتشغيله, ستلاحظ `code finished` أولا, ثم بعد ذلك`promise done!`. -That's strange, because the promise is definitely done from the beginning. +هذا غريب ، لأن الpromise يتم بالتأكيد من البداية. -Why did the `.then` trigger afterwards? What's going on? +لماذا تم تشغيل ".then" بعد ذلك؟ ماذا يحدث هنا؟ -## Microtasks queue +## طابور المهام الصغيرة -Asynchronous tasks need proper management. For that, the ECMA standard specifies an internal queue `PromiseJobs`, more often referred to as the "microtask queue" (ES8 term). +المهام عير المتزامنة بحاجة إلى إدارة سليمة. لذلك ، يحدد معيار ECMA قائمة انتظار داخلية `PromiseJobs` ، والتي يشار إليها غالبًا باسم" قائمة انتظار المهام المصغرة "(مصطلح ES8). -As stated in the [specification](https://tc39.github.io/ecma262/#sec-jobs-and-job-queues): +كما هو مذكور في [المواصفات] (https://tc39.github.io/ecma262/#sec-jobs-and-job-queues): -- The queue is first-in-first-out: tasks enqueued first are run first. -- Execution of a task is initiated only when nothing else is running. +- قائمة الانتظار هي أول ما يخرج أولاً: يتم تنفيذ المهام المحددة أولاً. +- يبدأ تنفيذ المهمة فقط في حالة عدم تشغيل أي شيء آخر. -Or, to say more simply, when a promise is ready, its `.then/catch/finally` handlers are put into the queue; they are not executed yet. When the JavaScript engine becomes free from the current code, it takes a task from the queue and executes it. - -That's why "code finished" in the example above shows first. +أو ، ببساطة ، عندما يكون الوعد جاهزًا ، يتم وضع معالجات "then / catch / وأخيرا" في قائمة الانتظار ؛ لم يتم إعدامهم بعد. عندما يصبح محرك JavaScript خاليًا من التعليمات البرمجية الحالية ، فإنه يأخذ مهمة من قائمة الانتظار وينفذها. +هذا هو السبب في أن "الرمز انتهى" في المثال أعلاه يظهر أولاً. ![](promiseQueue.svg) -Promise handlers always go through this internal queue. +تمر معالجات الوعد دائمًا من خلال قائمة الانتظار الداخلية هذه. -If there's a chain with multiple `.then/catch/finally`, then every one of them is executed asynchronously. That is, it first gets queued, then executed when the current code is complete and previously queued handlers are finished. +إذا كانت هناك سلسلة تحتوي على عدة ".then / catch / أخيرا" ، فسيتم تنفيذ كل واحد منها بشكل غير متزامن. أي أنه يتم وضعه في قائمة الانتظار أولاً ، ثم يتم تنفيذه عند اكتمال الرمز الحالي والانتهاء من معالجات قائمة الانتظار السابقة. -**What if the order matters for us? How can we make `code finished` run after `promise done`?** +** ماذا لو كان الأمر يهمنا؟ كيف يمكننا أن نجعل "الشفرة منتهية" تعمل بعد "الوعد"؟ ** -Easy, just put it into the queue with `.then`: +سهل ، ما عليك سوى وضعها في قائمة الانتظار باستخدام ".then`: ```js run Promise.resolve() @@ -50,17 +49,17 @@ Promise.resolve() .then(() => alert("code finished")); ``` -Now the order is as intended. +الآن الأمر كما هو مقصود. -## Unhandled rejection +## رفض غير معالج -Remember the `unhandledrejection` event from the article ? +هل تتذكر حدث `unhandledrejection` من المقالة ؟ -Now we can see exactly how JavaScript finds out that there was an unhandled rejection. +الآن يمكننا أن نرى بالضبط كيف تكتشف جافا سكريبت وجود رفض غير معالج. -**An "unhandled rejection" occurs when a promise error is not handled at the end of the microtask queue.** +** يحدث "رفض غير معالج" عندما لا تتم معالجة خطأ الوعد في نهاية قائمة المهام الدقيقة. ** -Normally, if we expect an error, we add `.catch` to the promise chain to handle it: +عادةً ، إذا توقعنا خطأ ، فإننا نضيف ".catch" إلى سلسلة الوعود للتعامل معه: ```js run let promise = Promise.reject(new Error("Promise Failed!")); @@ -72,7 +71,7 @@ promise.catch(err => alert('caught')); window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` -But if we forget to add `.catch`, then, after the microtask queue is empty, the engine triggers the event: +ولكن إذا نسينا إضافة ".catch" ، فعندما تصبح قائمة انتظار المهام الدقيقة فارغة ، يقوم المحرك بتشغيل الحدث: ```js run let promise = Promise.reject(new Error("Promise Failed!")); @@ -81,7 +80,7 @@ let promise = Promise.reject(new Error("Promise Failed!")); window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` -What if we handle the error later? Like this: +ماذا لو تعاملنا مع الخطأ لاحقًا؟ مثله: ```js run let promise = Promise.reject(new Error("Promise Failed!")); @@ -93,20 +92,20 @@ setTimeout(() => promise.catch(err => alert('caught')), 1000); window.addEventListener('unhandledrejection', event => alert(event.reason)); ``` -Now, if we run it, we'll see `Promise Failed!` first and then `caught`. +الآن ، إذا قمنا بتشغيله ، فسنرى "فشل الوعد!" أولاً ثم "تم الإمساك". -If we didn't know about the microtasks queue, we could wonder: "Why did `unhandledrejection` handler run? We did catch and handle the error!" +إذا لم نكن نعرف عن قائمة انتظار المهام الصغيرة ، فيمكننا أن نتساءل: "لماذا تم تشغيل معالج" عدم التعامل مع رفض "؟ لقد أمسكنا بالخطأ ومعالجته!" -But now we understand that `unhandledrejection` is generated when the microtask queue is complete: the engine examines promises and, if any of them is in the "rejected" state, then the event triggers. +ولكننا نفهم الآن أن "رفضًا غير معالَج" يتم إنشاؤه عند اكتمال قائمة انتظار المهام المصغرة: يقوم المحرك بفحص الوعود ، وإذا كان أي منها في حالة "مرفوضة" ، يتم تشغيل الحدث. -In the example above, `.catch` added by `setTimeout` also triggers. But it does so later, after `unhandledrejection` has already occurred, so it doesn't change anything. +في المثال أعلاه ، يتم تشغيل `.catch` بواسطة` setTimeout` أيضًا. ولكنه يفعل ذلك لاحقًا ، بعد حدوث "رفض غير معالَج" بالفعل ، لذلك لا يغير أي شيء. -## Summary +## ملخص -Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (ES8 term). +معالجة الوعد دائمًا غير متزامنة ، حيث تمر جميع إجراءات الوعد من خلال قائمة انتظار "وظائف الوعد" الداخلية ، والتي تسمى أيضًا "قائمة انتظار المهام المصغرة" (مصطلح ES8). -So `.then/catch/finally` handlers are always called after the current code is finished. +لذلك يتم دائمًا استدعاء معالجات `.then / catch / أخيرا` بعد انتهاء الكود الحالي. -If we need to guarantee that a piece of code is executed after `.then/catch/finally`, we can add it into a chained `.then` call. +إذا احتجنا إلى ضمان تنفيذ جزء من الرمز بعد ".then / catch / أخيرا" ، يمكننا إضافته إلى مكالمة ".then" المتسلسلة. -In most Javascript engines, including browsers and Node.js, the concept of microtasks is closely tied with the "event loop" and "macrotasks". As these have no direct relation to promises, they are covered in another part of the tutorial, in the article . +في معظم محركات جافا سكريبت ، بما في ذلك المتصفحات و Node.js ، يرتبط مفهوم المهام الدقيقة ارتباطًا وثيقًا بـ "حلقة الأحداث" و "المهام الكبيرة". نظرًا لأن هذه ليست لها علاقة مباشرة بالوعود ، فقد تم تناولها في جزء آخر من البرنامج التعليمي ، في المقالة . \ No newline at end of file