مدیریت خطاها در زبان برنامه نویسی جاوا اسکریپت

چهارشنبه 10 بهمن 1397

آشنایی با ارورهای جاوا اسکریپت می تواند بسیار مفید باشد، در این مطلب قصد داریم روش های مدیریت ارورهای جاوا اسکریپت را برای شما معرفی کنیم.

 مدیریت خطاها در زبان برنامه نویسی جاوا اسکریپت

من قصد دارم در این مطلب درباره ارورهای جاوا اسکریپت صحبت کنم، مطمئنم قبلاً این جمله را شنیده اید که ارورهای جاوا اسکریپت مفید هستند، در ابتدا ما از ارور های جاوا اسکریپت ترس داریم چرا که اغلب شاهد هستیم که صدمات جدی به برنامه وارد می ‌کنند. ما در واقع در این مطلب قصد داریم یاد بگیریم که چه کارهایی را انجام ندهیم و چه کارهایی را انجام دهیم تا بعدها به نفع ما باشد. همه شما با خطاها و اشتباهاتی که در زندگی عادی ما پیش می‌ آید آشنا هستید. خطاهای برنامه نویسی و ارورهای جاوا اسکریپت کمی متفاوت هستند، آنها در واقع یک سری ویژگی هایی هستند که به ما کمک می کنند تا قدرت برنامه نویسی خود را بهبود ببخشیم و به کاربر هنگامی که قسمتی از برنامه دچار خطا می‌شود مشکل اعلام می کنند.

نگاهی کلی به این مقاله

این مقاله دارای ۳ قسمت می باشد، در ابتدا ما یک نگاه کلی به ارورهای جاوا اسکریپت خواهیم داشت، پس از آن بر روی بک اند تمرکز می ‌کنیم و در نهایت روش مقابله با ارورهای جاوا اسکریپت در ReactJS را بررسی خواهیم کرد. من این فریم ورک ها انتخاب کرده ام چرا که آنها بسیار محبوب هستند، اما شما می توانید با به دست آوردن اطلاعات کافی درباره مدیریت ارورهای جاوا اسکریپت به راحتی دانش خود را در فریم ورک های دیگر نیز اعمال کنید.

ارورهای جاوا اسکریپت و مدیریت عمومی آن ها

دستور throw new Error(‘something went wrong’) یک شی از ارورهای جاوا اسکریپت می‌ سازد و اجرای اسکریپت شما را متوقف می کند،  مگر آنکه شما اقداماتی را برای ارورهای جاوا اسکریپت اندیشیده باشید. هنگامی که شما کار خود را به عنوان توسعه دهنده جاوا اسکریپت آغاز می کنید به احتمال زیاد این کار را انجام خواهید داد بلکه برای انجام دادن آن از سایر کتابخانه هایی که برای انجام این کار وجود دارند استفاده خواهید کرد، به عنوان مثال می ‌توانید از کتابخانه هایی همچون ReferenceError:fs not defined یا موارد مشابه آن استفاده کنید.

شی ارورهای جاوا اسکریپت

شی ارورهای جاوا اسکریپت دارای دو ویژگی است که برای استفاده ما ساخته شده است، اولین مورد پیام ارورهای جاوا اسکریپت است که شما می توانید به عنوان آرگومان به صورت زیر به کاستراکتور ارسال کنید:

New Error(‘This is the message’)

شما می توانید از طریق ویژگی message به پیام یک ارور دسترسی پیدا کنید:

const myError = new Error(‘please improve your code’)

console.log(myError.message) // please improve your code

ویژگی بسیار مهم دیگر ارور های جاوا اسکریپت stack trace است که شما می توانید از طریق ویژگی stack به آن دسترسی داشته باشید.  Stack trace به شما یک تاریخچه و سابقه از آنچه که باعث به وجود آمدن ارورهای جاوا اسکریپت شده است می دهد. در بالای این استک پیغام ارور های جاوا اسکریپت وجود دارد و در ادامه آن می توانید دلایل به وجود آمدن این ارور ها را ببینید.

Error: please improve your code
 at Object.<anonymous> (/Users/gisderdube/Documents/_projects/hacking.nosync/error-handling/src/general.js:1:79)
 at Module._compile (internal/modules/cjs/loader.js:689:30)
 at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
 at Module.load (internal/modules/cjs/loader.js:599:32)
 at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
 at Function.Module._load (internal/modules/cjs/loader.js:530:3)
 at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
 at startup (internal/bootstrap/node.js:266:19)
 at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)

به وجود آوردن و مدیریت ارورهای جاوا اسکریپت

درست کردن یک شی از ارورهای جاوا اسکریپت به تنهایی باعث اتفاق خاصی نمی شود، یعنی استفاده از دستور new Error(..) به تنهایی کاری نمی کند. زمانی که یک خطا به وجود می آید کمی جالب تر می شود، زمانی که ارورهای جاوا اسکریپت به وجود می آیند همانطور که قبلا گفته شد اجرای اسکریپت شما متوقف می شود مگر این که شما به نحوی آن را مدیریت کرده باشید، توجه داشته باشید که مهم این نیست این ارورهای جاوا اسکریپت به صورت دستی توسط شما، توسط یک کتابخانه و یا توسط runtime به وجود آمده باشند. بیایید کمی درباره برخورد با ارورهای جاوا اسکریپت در سناریوهای مختلف صحبت کنیم.

ساختار try … catch

این راه ساده ترین راه برای مدیریت ارورهای جاوا اسکریپت است ولی امروزه به لطف async/await کمتر مورد استفاده قرار می گیرد. این ساختار مانند مثال زیر می تواند برای مدیریت هرگونه ارورهای همزمانی در جاوا اسکریپت مورد استفاده قرار گیرد:

const a = 5

try {
    console.log(b) // b is not defined, so throws an error
} catch (err) {
    console.error(err) // will log the error with the error stack
}

console.log(a) // still gets executed
                            

اگر ما از console.Log(b) درون try استفاده نکنیم اجرای برنامه متوقف می شود.

استفاده از finally

گاهی اوقات لازم است که کدی بنویسید که هم زمانی که ارورهای جاوا اسکریپت اتفاق افتادند اجرا شود و هم هنگامی که اتفاق نیفتادند، شما می توانید از یک بلاک سوم و اختیاری برای این کار استفاده کنید که نام آن بلاک finally می باشد. گاهی اوقات این دستور دقیقا مانند این است که شما یک خط دستور بعد از try  و catch داشته باشید اما گاهی اوقات نیز بسیار مفید می باشد:

const a = 5

try {
    console.log(b) // b is not defined, so throws an error
} catch (err) {
    console.error(err) // will log the error with the error stack
} finally {
    console.log(a) // will always get executed
}

فراخوانی توابع asynchronicity

ناهمزمانی یکی از مسائلی است که همواره زمانی که شما در حال کار کردن با جاوا اسکریپت هستید باید آن را در نظر داشته باشید، زمانی که شما یک تابع ناهمزمان دارید و یکی از ارورهای جاوا اسکریپت درون تابع شما اتفاق می افتد اجرای برنامه شما ادامه پیدا می کند، بنابراین بلافاصله خطایی در برنامه شما ایجاد نمی شود زمانی که شما تابع همزمان خود را فراخوانی می کنید( با هر روشی)، شما معمولا دو پارامتر در فراخوانی تابع دریافت می کنید که چیزی شبیه به این می باشد:

myAsyncFunc(someInput, (err, result) => {
    if(err) return console.error(err) // we will see later what to do with the error object.
    console.log(result)
})

اگر در این جا یکی از ارورهای جاوا اسکریپت وجود داشته باشد پارامتر err آن ارور را نشان خواهد داد و در غیر این صورت این پارامتر undefined و یا null خواهد بود. این نکته بسیار مهم است که یا چیزی را درون بلاک if برگردانید و یا یک درون بلاک else دستور دیگری قرار دهید، در غیر این صورت ممکن است یکی دیگر از ارورهای جاوا اسکریپت برای شما اتفاق بیفتد. به عنوان مثال فرض کنید نتیجه Undefined است و شما سعی دارید به result.data دسترسی پیدا کنید.

استفاده از Promises برای ناهمزمانی

یکی از بهترین راه ها برای تعامل با ناهمزمانی استفاده از Promises می باشد، در این روش علاوه بر افزایش خوانایی کد می توان ارورهای جاوا اسکریپت را نیز مدیریت کرد. تا زمانی که یک بلاک catch داریم دیگر نیازی نیست که نسبت به نوع دقیق اروری که اتفاق افتاده است نگران باشیم. زمانی که ما promises را فراخوانی می کنیم تمامی ارورهای ما از آن جایی که آن را فراخوانی کرده ایم و یا از آخرین بلاک catch مدیریت خواهند شد. توجه داشته باشید که استفاده از Promises بدون استفاده از بلاک catch برنامه را خاتمه نمی دهد ولی خوانایی کمتری دارد. مثال زیر را در نظر بگیرید:

Promise.resolve(1)
    .then(res => {
        console.log(res) // 1

        throw new Error('something went wrong')

        return Promise.resolve(2)
    })
    .then(res => {
        console.log(res) // will not get executed
    })
    .catch(err => {
        console.error(err) // we will see what to do with it later
        return Promise.resolve(3)
    })
    .then(res => {
        console.log(res) // 3
    })
    .catch(err => {
        // in case in the previous block occurs another error
        console.error(err)
})

استفاده دوباره از try … catch

بعد از معرفی async/await در مدیریت ارورهای جاوا اسکریپت ما دوباره برمی گردیم به اصلی ترین روش برای حل برای مدیریت ارورهای جاوا اسکریپت با استفاده از try…catch…finally.

;(async function() {
    try {
        await someFuncThatThrowsAnError()
    } catch (err) {
        console.error(err) // we will make sense of that later
    }

    console.log('Easy!') // will get executed
})()

از آن جایی که این همان روشی است که ما برای مدیریت ارورهای نرمال جاوا اسکریپت و ارورهای ناهمزمانی استفاده کردیم، این روش استفاده بیشتری نسبت به استفاده از دستورات if  برای catch کردن ارورهای جاوا اسکریپت دارد.

تولید و مدیریت ارورهای جاوا اسکریپت در سمت سرور

حال که ما ابزارهایی برای مدیریت ارورهای جاوا اسکریپت داریم، بیاید ببینیم در شرایط واقعی با ارورهای جاوا اسکریپت چگونه برخورد می کنیم. تولید و مدیریت خطاهای جاوا اسکریپت در قسمت بک اند حیاتی ترین بخش از اپلیکیشن شما می باشد. رویکردهای متفاوتی برای مدیریت ارورهای جاوا اسکریپت در بک اند وجود دارد، من به شما یک رویکرد با کانستراکتور و کدهای مربوط به ارورهای جاوا اسکریپت که شخصی سازی شده اند را نشان می دهم که می توانید آن را به فرانت اند اپلیکیشن و یا هر مصرف کننده API دیگری ارسال کنید. این که چطور به صورت جزئی بک اند خود را بسازید خیلی مهم نیست چرا که ایده همان است.

ما برای این کار از فریم ورک Express.js استفاده می کنیم اجازه دهید بیشتر درباره ساختاری که می خواهیم برای مدیریت ارورهای جاوا اسکریپت ارائه دهیم صحبت کنیم. ما موارد زیر را می خواهیم:

مدیریت ارورهای عمومی، برخی از انواع fallback و به صورت کلی بگوید:

"چیزی غلط است، لطفا دوباره تکرار کنید و یا با ما تماس بگیرید." این کار هوشمندانه نیست اما حداقل به جای این که بی نهایت بار تکرار شود به کاربر اطلاع می دهد که چیزی غلط است.

مدیریت خطاهای جاوا اسکریپت به صورت خاص که به کاربر اطلاعاتی درباره جزئیات نوع خطایی که رخ داده است بدهد و بگوید که کدام یک از انواع ارورهای جاوا اسکریپت رخ داده است و برای انجام آن چه کاری باید انجام شود؟ در این جا برخی از اطلاعات از دست می رود اما تمامی آن ها در دیتابیس موجود است.

ساخت کانستراکتورهای ارورهای جاوا اسکریپت به صورت شخصی سازی شده

ما از کانستراکتور ارورهای جاوا اسکریپت که وجود دارد استفاده می کنیم و از آن ارث بری می کنیم. ارث بری در جاوا اسکریپت یک کار ریسکی و خطرناک می باشد، اما در این مورد من تجربه کردم که بسیار مفید است، چرا ما به آن نیاز داریم؟ ما هنوزم هم می خواهیم از stack trace استفاده کنیم تا یک تجربه خوب در دیباگ کردن ارورهای جاوا اسکریپت داشته باشیم. ارث برای از کانستراکتور اصلی ارورهای جاوا اسکریپت به ما به صورت رایگان یک stack trace می دهیم، تنها باید یک کد را به آن اضافه کنیم که ما بعدا از طریق دستور err.code به آن دسترسی پیدا می کنیم.

class CustomError extends Error {
    constructor(code = 'GENERIC', status = 500, ...params) {
        super(...params)

        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, CustomError)
        }

        this.code = code
        this.status = status
    }
}

module.exports = CustomError

چگونه routing را مدیریت کنیم؟

حالا که ارورهای شخصی سازی آماده است باید ساختار routing را نصب کنیم، همان طور که گفتم ما یک نقطه صحیح در برنامه می خواهیم برای مدیریت ارورهای جاوا اسکریپت، این به آن معناست که برای هر کدام از routing ما همان رفتار مدیریت ارورها را داشته باشیم. از آن جایی که تمامی route ها محدود شده اند، به صورت دیفالت express نمی تواند آن را انجام دهد.

حل این مسئله

برای حل این مسئله ما می توانیم یک route handler را اجرا کنیم و بعد از آن منطق route خود را برای آن تعریف کنیم. در این روش تابع route( و یا هر تابعی که درون آن قرار دارد) یک ارور ایجاد می کند که می تواند به route handler باز گردد و بعد از آن نیز می تواند آن را به قسمت فرانت اند ارسال کند. هر زمان که اروری در بک اند به وجود می آید ما می خواهیم یک response به فرانت اند ارسال کنیم. فرض کنید یک JSON API با فرمت زیر:

{
    error: 'SOME_ERROR_CODE',
    description: 'Something bad happened. Please try again or     contact support.'
}

خودتان را آماده کنید که غرق شوید، زمانی که من جمله زیر را می گویم دانش آموزانم بسیار عصبانی می شوند:

اشکالی ندارد که در تلاش اول همه چیز را متوجه نمی شوید، فقط از آن استفاده کنید و مطمئن باشید بعدها شما احساس می کنید که چرا آن مهم است. این نوع یادگیری را یادگیری بالا به پایین می گویند که من یکی از طرفداران بزرگ آن هستم.

Route handler نیز دقیقا مشابه همین است. 

کدهای قسمت 

حال با کدهای مربوط به ارورهای جاوا اسکریپت که در قسمت قبل گفتیم آشنا می شویم:

const express = require('express')
const router = express.Router()
const CustomError = require('../CustomError')

router.use(async (req, res) => {
    try {
        const route = require(`.${req.path}`)[req.method]

        try {
            const result = route(req) // We pass the request to the route function
            res.send(result) // We just send to the client what we get returned from the route function
        } catch (err) {
            /*
            This will be entered, if an error occurs inside the route function.
            */
            if (err instanceof CustomError) {
                /* 
                In case the error has already been handled, we just transform the error 
                to our return object.
                */

                return res.status(err.status).send({
                    error: err.code,
                    description: err.message,
                })
            } else {
                console.error(err) // For debugging reasons

                // It would be an unhandled error, here we can just return our generic error object.
                return res.status(500).send({
                    error: 'GENERIC',
                    description: 'Something went wrong. Please try again or contact support.',
                })
            }
        }
    } catch (err) {
        /* 
        This will be entered, if the require fails, meaning there is either 
        no file with the name of the request path or no exported function 
        with the given request method.
        */
        res.status(404).send({
            error: 'NOT_FOUND',
            description: 'The resource you tried to access does not exist.',
        })
    }
})

module.exports = router

توضیح کدهای بالا

امیدوارم که بتوانید کامنت ها و توضیحات کد را مطالعه کنید، من فکر کردم که این کامنت ها بهتر از هر توضیحی برای شما هستند، حال بگذارید ببینیم که یک فایل route واقعی شبیه کد زیر چه چیزی است:

const CustomError = require('../CustomError')

const GET = req => {
    // example for success
    return { name: 'Rio de Janeiro' }
}

const POST = req => {
    // example for unhandled error
    throw new Error('Some unexpected error, may also be thrown by a library or the runtime.')
}

const DELETE = req => {
    // example for handled error
    throw new CustomError('CITY_NOT_FOUND', 404, 'The city you are trying to delete could not be found.')
}

const PATCH = req => {
    // example for catching errors and using a CustomError
    try {
        // something bad happens here
        throw new Error('Some internal error')
    } catch (err) {
        console.error(err) // decide what you want to do here

        throw new CustomError(
            'CITY_NOT_EDITABLE',
            400,
            'The city you are trying to edit is not editable.'
        )
    }
}

module.exports = {
    GET,
    POST,
    DELETE,
    PATCH,
}

توضیح مثال بالا از ارورهای جاوا اسکریپت

در این مثال من با درخواست واقعی کاری انجام نمی دهم، من فقط سناریو ارورهای مختلف جاوا اسکریپت را جعل می کنم، بنابراین به عنوان مثال دستور Get/city در خط سوم به پایان خواهد رسید و همینطور POST/city در خط هشتم به پایان خواهد رسید و ... . این در واقع با پارامترهای کوئری کار می کند. در اصل شما یکی از ارورهای جاوا اسکریپت که مدیریت نشده را خواهید داشت که فرانت اند آن را به شکل زیر دریافت می کند:

{
    error: 'GENERIC',
    description: 'Something went wrong. Please try again or contact support.'
}

و یا شما یکی از ارورهای جاوا اسکریپت که شخصی سازی شده است را به صورت دستی به شکل زیر به وجود می آورید:

throw new CustomError('MY_CODE', 400, 'Error description')

که به کد زیر تبدیل می شود:

{
    error: 'MY_CODE',
    description: 'Error description'
}

حال که ما این تنظیمات زیبای بک اند را در اختیار داریم ما دیگر هیچ خطای ناشناخته ای در فرانت اند نخواهیم داشت و اطلاعات قابل استفاده درباره ارورهای جاوا اسکریپت که اتفاق افتاده اند به ما برمی گردد.

نشان دادن ارورهای جاوا اسکریپت به کاربر

گام بعدی و در واقع آخرین گام مدیریت ارورهای جاوا اسکریپت در فرانت اند می باشد، در این جا شما می خواهید ارورهای جاوا اسکریپت که توسط منطق فرانت اند اپلیکیشن شما ایجاد شده اند را با استفاده از ابزاری که در قسمت اول معرفی شدند مدیریت کنید، اگر چه ارورهای جاوا اسکریپت که در بک اند به وجود می آیند نیز باید نشان داده شوند. بیایید ابتدا ببینیم چگونه باید ارورهای جاوا اسکریپت را نمایش دهیم. همانطور که قبلا گفته شد ما می توانیم از React در برنامه خود استفاده کنیم.

ذخیره کردن ارورهای جاوا اسکریپت در استیت React

درست مانند سایر داده ها ارورهای جاوا اسکریپت و پیغام های ارورهای جاوا اسکریپت می توانند تغییر کنند، بنابراین شما می خواهید آن ها را درون state کامپوننت های جداگانه قرار دهید. به طور پیش فرض و در هنگام نصب شما می خواهید که ارورهای جاوا اسکریپت را مجددا تنظیم کنید، بنابراین زمانی که کاربر برای اولین بار صفحه را می بیند هیچ اروری را مشاهده نمی کند. چیز دیگری که باید آن را برای شما روشن کنیم انواع مختلف ارورهای جاوا اسکریپت به همراه روش های به نمایش گذاشتن آن ها است. همانطور که قبلا گفتیم سه نوع ارور در بک اند وجود دارد که در ادامه معرفی خواهیم کرد.

انواع ارورهای جاوا اسکریپت

ارورهای جاوا اسکریپت را می توان به چند دسته زیر تقسیم بندی کرد:

1. ارورهای global: به عنوان مثال یکی از خطاهای عمومی ممکن است از بک اند بیایند و یا ممکن است کاربر signin نشده باشد و ... .

2. ارورهای خاص که از بک اند می آیند، کاربر مشخصات خود را به بک اند ارسال می کند. بک اند پاسخ می دهد که پسورد درست نیست، این موضوع توسط فرانت اند تایید نمی شود، بنابراین حتما باید توسط بک اند انجام شود.

3. ارورهای خاصی که توسط فرانت اند ایجاد می شوند، به عنوان مثال اعتبار سنجی یکی از فیلدهای ایمیل.

مورد دوم و سوم بسیار مشابه هستند و در همان لحظه مدیریت می شوند( اگر بخواهیم) اما دارای یک تفاوت اصلی هستند، ما در کد می‌بینیم که آنها چگونه کار می کنند.

من می خواهم از اجرای state در React Native استفاده کنم، اما شما می توانید از ابزارهای مدیریت state مانند MOBX و یا Redux استفاده کنید.

ارورهای جاوا اسکریپت به صورت گلوبال

معمولا من این ارورهای جاوا اسکریپت را در کامپوننت های خارج از رده مقدماتی ذخیره می کنم و یک عنصر رابط گرافیکی استاتیک را رندر می کنم، این می تواند همچون یک پرده قرمز رنگ در بالای صفحه نمایش شما نشان داده شود.

مثالی از عنصر رابط گرافیکی برای ارورهای گلوبال

بگذارید مثال زیر را در نظر بگیریم:

import React, { Component } from 'react'

import GlobalError from './GlobalError'

class Application extends Component {
    constructor(props) {
        super(props)

        this.state = {
            error: '',
        }

        this._resetError = this._resetError.bind(this)
        this._setError = this._setError.bind(this)
    }

    render() {
        return (
            <div className="container">
                <GlobalError error={this.state.error} resetError={this._resetError} />
                <h1>Handling Errors</h1>
            </div>
        )
    }

    _resetError() {
        this.setState({ error: '' })
    }

    _setError(newError) {
        this.setState({ error: newError })
    }
}

export default Application

توضیح این مثال از ارورهای جاوا اسکریپت

همانطور که می توانید مشاهده کنید ما یک ارور ر state در اپلیکیشن داریم، ما همچنین توابعی داریم تا مقادیر ارورها را تغییر دهیم و یا آن را reset کنیم. ما مقدار را ارسال می کنیم و تابع ریست آن را ریست می کند. اجازه دهید ببینیم چگونه GlobalErr کار می کند:

import React, { Component } from 'react'

class GlobalError extends Component {
    render() {
        if (!this.props.error) return null

        return (
            <div
                style={{
                    position: 'fixed',
                    top: 0,
                    left: '50%',
                    transform: 'translateX(-50%)',
                    padding: 10,
                    backgroundColor: '#ffcccc',
                    boxShadow: '0 3px 25px -10px rgba(0,0,0,0.5)',
                    display: 'flex',
                    alignItems: 'center',
                }}
            >
                {this.props.error}
                &nbsp;
                <i
                    className="material-icons"
                    style={{ cursor: 'pointer' }}
                    onClick={this.props.resetError}
                >
                    close
                </i>
            </div>
        )
    }
}

export default GlobalError

export default GlobalError

همانطور که می توانید در خط پنج مشاهده کنید اگر هیچ یک از ارورهای جاوا اسکریپت رخ ندهد ما هیچ چیزی را رندر نمی کنیم، این کار باعث می شود که ما نوارهای قرمز رنگ خالی نداشته باشیم. توجه داشته باشید که شما می توانید کارکرد این کامپوننت را تغییر دهید، به عنوان مثال شما می توانید ‘x’ را با ارور timeout تعویض کنید که حالت ارورهای جاوا اسکریپت را بعد از گذشت مدت زمانی تغییر دهد. حالا شما می توانید هر جایی که خواستید از این global error state استفاده کنید، برای این کار تنها کافی است _setError را از Application.js منتقل کنید و بعد از آن می توانید global error را تنظیم کنید.

یک مثال دیگر

import React, { Component } from 'react'
import axios from 'axios'

class GenericErrorReq extends Component {
    constructor(props) {
        super(props)

        this._callBackend = this._callBackend.bind(this)
    }

    render() {
        return (
            <div>
                <button onClick={this._callBackend}>Click me to call the backend</button>
            </div>
        )
    }

    _callBackend() {
        axios
            .post('/api/city')
            .then(result => {
                // do something with it, if the request is successful
            })
            .catch(err => {
                if (err.response.data.error === 'GENERIC') {
                    this.props.setError(err.response.data.description)
                }
            })
    }
}

export default GenericErrorReq

یک نکته مهم درباره ارورهای جاوا اسکریپت

اگر تنبل هستید تا همین جا کافی است، حتی اگر شما یکی از ارورهای جاوا اسکریپت را دارید که یک ارور خاص است تنها کافی است global error state را تغییر دهید و آن را در یک نوار بالای صفحه به نمایش بگذارید. با این حال من می خواهم به شما نشان دهم که چگونه خاص ترین ارورهای جاوا اسکریپت را مدیریت کنید و آن ها را نمایش دهید. چرا؟ اولا این یک راهنمایی کامل درباره مدیریت ارورهای جاوا اسکریپت است، بنابراین من نمی توانم آن را در این نقطه متوقف کنم. دوما برنامه نویسان UX احتمالا اگر شما تمامی ارورهای جاوا اسکریپت را به صورت global  نمایش دهید تعجب می کنند.

مدیریت ارورهای خاص در جاوا اسکریپت

مشابه ارورهای گلوبال ما می توانیم یک Error state محلی درون کامپوننت های دیگر داشته باشیم، روش این کار به شکل زیر می باشد:

import React, { Component } from 'react'
import axios from 'axios'

import InlineError from './InlineError'

class SpecificErrorRequest extends Component {
    constructor(props) {
        super(props)

        this.state = {
            error: '',
        }

        this._callBackend = this._callBackend.bind(this)
    }

    render() {
        return (
            <div>
                <button onClick={this._callBackend}>Delete your city</button>
                <InlineError error={this.state.error} />
            </div>
        )
    }

    _callBackend() {
        this.setState({
            error: '',
        })

        axios
            .delete('/api/city')
            .then(result => {
                // do something with it, if the request is successful
            })
            .catch(err => {
                if (err.response.data.error === 'GENERIC') {
                    this.props.setError(err.response.data.description)
                } else {
                    this.setState({
                        error: err.response.data.description,
                    })
                }
            })
    }
}

export default SpecificErrorRequest

نکته ای که باید به یاد داشته باشید این است که از بین بردن خطا معمولا یک روند متفاوت می باشد. در هنگام ایجاد یک درخواست جدید بهتر است که ارور را پاک کنید، همچنین می توانید زمانی که کاربر تغییری را ایجاد می کند نیز این کار را انجام دهید، به عنوان مثال زمانی که کاربر مقدار ورودی را تغییر می دهد.

ارورهای جاوا اسکریپت در فرانت اند

همان طور که به زودی گفته می شود این ارورهای جاوا اسکریپت نیز با همان روش که برای ارورهای جاوا اسکریپت که از بک اند می آیند استفاده می شد ( روش state) مدیریت می شوند، اجازه دهید با یک مثال که در آن یک فیلد ورودی وجود دارد شروع کنیم که به کاربر اجازه می دهد نام یک شهر را حذف کند:

import React, { Component } from 'react'
import axios from 'axios'

import InlineError from './InlineError'

class SpecificErrorRequest extends Component {
    constructor(props) {
        super(props)

        this.state = {
            error: '',
            city: '',
        }

        this._callBackend = this._callBackend.bind(this)
        this._changeCity = this._changeCity.bind(this)
    }

    render() {
        return (
            <div>
                <input
                    type="text"
                    value={this.state.city}
                    style={{ marginRight: 15 }}
                    onChange={this._changeCity}
                />
                <button onClick={this._callBackend}>Delete your city</button>
                <InlineError error={this.state.error} />
            </div>
        )
    }

    _changeCity(e) {
        this.setState({
            error: '',
            city: e.target.value,
        })
    }

    _validate() {
        if (!this.state.city.length) throw new Error('Please provide a city name.')
    }

    _callBackend() {
        this.setState({
            error: '',
        })

        try {
            this._validate()
        } catch (err) {
            return this.setState({ error: err.message })
        }

        axios
            .delete('/api/city')
            .then(result => {
                // do something with it, if the request is successful
            })
            .catch(err => {
                if (err.response.data.error === 'GENERIC') {
                    this.props.setError(err.response.data.description)
                } else {
                    this.setState({
                        error: err.response.data.description,
                    })
                }
            })
    }
}

export default SpecificErrorRequest

Error internationalation با استفاده از کدهای مربوط به ارور

ممکن است شما تعجب کرده باشید که ما چرا باید کدهای ارورهای بالا را داشته باشیم، به عنوان مثال GENERIC، ما فقط توضیحات مربوط به ارورهای جاوا اسکریپت را که به بک اند ارسال می شوند نشان می دهیم. حال زمانی که اپلیکیشن شما رشد کند شما می توانید امیدوار باشید که مارکت های جدیدی داشته باشید و در بعضی موارد در مواجهه با مشکلات مختلف بتوانید آن ها را با استفاده از زبان های برنامه نویسی مختلف حل کنید. اگر شما در این نقطه هستید شما می توانید از کدهای مربوط به ارورهای جاوا اسکریپت که گفته شد استفاده کنید تا بتوانید توضیحات درستی را به کاربر نمایش دهید.

جمع بندی ارورهای جاوا اسکریپت

امیدوارم اطلاعات کافی درباره این که چگونه با ارورهای جاوا اسکریپت برخورد کنید را بدست آورده باشید، یکی از مهم ترین توصیه های من به شما این است که از

log level هم حتما استفاده کنید.

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

تاکنون هیچ کاربری از این پست تشکر نکرده است

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید