متخصصین علوم رایانه کشور

Learning MEAN Framework
متخصصین علوم رایانه کشور

۳ مطلب با موضوع «JAVASCRIPT» ثبت شده است

۲۲
آذر
موضوع:‌ آموزش Callback Pattern - Creating Asynchronous Function
ویرایش:‌ ۱.۱

اجازه دهید مجددا بخشی از سورس‌کدی که در قسمت سوم آموزشی،‌ نوشته‌ایم را بررسی نماییم:

server.listen(3000);
console.log('Web server is listening...');

این کد، کد مناسبی نمی‌باشد! ولی علت چیست؟ واقعیت آن است که دستورات JavaScript چه در سمت Client و چه در سمت Server، به ترتیب اجرا می‌شوند و بسیاری از دستورات پیش‌فرض، مانند دستور listen، به صورت Async اجرا می‌شوند. این بدان معنی است که پس از فرآخوانی دستوری مانند server.listen، سیستم در این خط دچار وقفه نشده و به سرعت سراغ دستور بعدی می‌رود. حال فرض کنید که اجرای دستور listen، به هر دلیلی، پنج ثانیه به طول بیانجامد. در این صورت شما پیام Web server is listening را پنج ثانیه قبل از راه‌اندازی واقعی و در محیط Console خواهید دید! که این اصلا درست نمی‌باشد. از آن بدتر! زمانی است که راه‌اندازی Server به مشکل برخورد کرده و اصلا راه اندازی نشود، در این صورت باز هم شما پیام مذکور را خواهید دید که سرور به درستی راه‌اندازی شده و منتظر درخواست از طرف Client می‌باشد!
با توجه به نکات فوق، به این نتیجه می‌رسیم که باید دستورات فوق را به گونه دیگری بنویسیم. حال به دستورات ذیل توجه نمایید:

server.listen(3000, function(error) {

    if(error != null) {
        console.log('Web server can't listen! - ' + error);
        return;
    }

    console.log('Web server is listening...');
});

کد فوق، یک کد هوشمندانه و مناسب می‌باشد! به محض اینکه سیستم، به دستور server.listen می‌رسد، متوجه می‌شود که باید این دستور را اجرا کند و اقدام به اجرای آن می‌کند. ولی معطل اجرای آن نمی‌شود! و به سرعت، به سراغ دستورات بعد از server.listen خواهد رفت. ولی هرگاه عملیات مربوط به server.listen (چه با خطا و یا بدون خطا) خاتمه یابد، وارد تابع درونی server.listen می‌شود. در صورتی که کار با موفقیت صورت نگرفته باشد، شیء error مخالف null بوده، که در این صورت، پیام خطا در محیط کنسول نمایش داده می‌شود و در صورتی که عملیات با موفقیت صورت گرفته باشد، پیام Web server is listening، در محیط کنسول نمایش داده خواهد شد.
به تابع درونی server.listen، اصطلاحا Callback Function می‌گویند، و به خود تابع listen، یک تابع Asynchronous اطلاق می‌شود و ما به کرات از اینگونه توابع، در هنگام برنامه‌نویسی در محیط‌های Client و یا Server برخورد خواهیم کرد.
ولی چیزی که از مطلب فوق اهمیت بیشتری دارد، آن است که یاد بگیریم، چگونه تفکر و یا الگوی Callback را پیاده‌سازی نماییم، و چگونه اقدام به نوشتن یک توابع Asynchronous نماییم. فرض کنید که ما یک یا چند دستور سنگین داریم که اجرای آنها زمان زیادی را به خود اختصاص می‌دهند. به عنوان مثال فرض کنید، می‌خواهیم یک Data Conversion سنگین انجام دهیم، که به طور تقریبی، ۶۰ ثانیه به طول می‌انجامد. توجه داشته باشید که در محیط‌های Client‌ و یا Server، اجرای دستورات JavaScript، فقط با یک Thread انجام می‌شوند. لذا اگر یکی از کاربران سیستم، باعث شود که اجرای برنامه، به دستورات سنگینی برخورد نماید، متاسفانه تمام کاربران سایت، به مدت ۶۰ ثانیه معطل اجرای دستورات مختص به خود خواهند شد، و این یک فاجعه است! لذا می‌خواهیم الگویی را یاد بگیریم که مناسب اینگونه شرایط است.
برای این منظور، ابتدا دستوراتی که اجرای آنها زمان زیادی را به خود اختصاص می‌دهند را در داخل یک تابع جداگانه‌ای می‌نویسیم. در مثال ذیل، فرض بر این است که تابع مذکور، دارای پارامتر ورودی خاصی نمی‌باشد. در این حالت فقط یک پارامتر ورودی به نام callback، برای تابع مذکور، تعریف می‌کنیم. دقت داشته باشید، در صورتی که بخواهیم برای تابع مذکور، به عنوان مثال، دو پارامتر a و b ارسال نماییم، باید تعداد پارامترهای تابع مذکور را برابر سه پارامتر تعریف نماییم و باید پارامتر آخر آن callback باشد.
پس از نوشتن تابع مذکور، در درون آن از دستور setTimeout استفاده می‌کنیم. دقت داشته باشید که این تابع، کلید Callback Pattern می‌باشد. در شرایط عادی،‌ از این تابع، زمانی استفاده می‌کنیم که بخواهیم دستور یا دستوراتی را پس از گذشت چند میلی ثانیه، اجرا نماییم. ولی در حال حاضر، نیت و هدف دیگری داریم! با استفاده از این تابع، می‌توانیم الگوی Callback را پیاده‌سازی نماییم. لذا در داخل تابع مذکور، تابع setTimeout را نوشته و زمان اجرای آنرا، برابر صفر در نظر می‌گیریم.
function calculateSalary(callback) {
setTimeout(function () {

// Do some process(es) for calculating salary.
for (var index = 1; index <= 1000000000; index++) {
}

callback();
}, 0);
}
در دستورات فوق، فرض بر آن است که دستور for، همان دستوری است که اجرای آن زمان زیادی را به خود اختصاص می‌دهد.
حال زمانی که می‌خواهیم دستورات سنگین و پر هزینه از نظر زمانی مذکور را اجرا نماییم، به صورت ذیل عمل می‌کنیم:

calculateSalary(function () {
console.log('Salary Calculation Done!');
});

حال نمونه دیگری را با هم بررسی می‌کنیم. نمونه‌ای که در آن، تابع مربوطه، به عنوان مثال، دارای دو پارامتر ورودی a‌ و b‌ می‌باشد.

function calculateSalary(a, b, callback) {
setTimeout(function () {

// Do some process(es) for calculating salary.
for (var index = 1; index <= 1000000 * a * b; index++) {
}

callback();
}, 0);
}

calculateSalary(5, 10, function () {
console.log('Salary Calculation Done!');
});


در دو نمونه فوق، دو مشکل اساسی داریم:
۱. در صورتی که اجرای تابع، به مشکلی برخورد کند، راه حل مناسبی پیشنهاد نشده است!
۲. در صورتی که نیاز داشته باشیم که تابع مذکور خروجی در اختیار ما قرار دهد نیز راه حل مناسبی پیشنهاد نشده است!
حال اجازه دهید که بهترین و هوشمندانه‌ترین راه حل را با هم و به کمک مثال ذیل پی می‌گیریم. در مثال ذیل، اولا برای تابع خود، پارامترهای ورودی داریم به نام‌های a و b در نظر گرفته‌ایم، و نیز، در صورت بروز خطا در زمان اجرای تابع مذکور، روش علمی و مناسبی ارایه کرده‌ایم و ثالثا، مقداری را به عنوان نتیجه و یا خروجی تابع ایجاد کرده و برمی‌گردانیم:

function division(a, b, callback) {
setTimeout(function () {

// Do some process(es) for calculating salary.
for (var index = 1; index <= 1000000000; index++) {
}

if (b == 0) {
var error =
new Error('Division by zero!');

callback(error, null);
}
else {
var result = a / b;

callback(null, result);
}
}, 0);
}

division(10, 2, function (error, result) {

if (error != null) {
console.log(error);
}
else {
console.log('Result: ' + result);
}
});

division(5, 0, function (error, result) {

if (error != null) {
console.log(error.message);
}
else {
console.log('Result: ' + result);
}
});

console.log('This message will be shown Immediately!');

  • داریوش تصدیقی
۱۲
آبان

Functions are Objects

The typeof operator in JavaScript returns "function" for functions.

But, JavaScript functions can best be described as objects.

JavaScript functions have both properties and methods.

The arguments.length property returns the number of arguments received when the function was invoked:


در زبان جاوا اسکریپت، با استفاده از دستور typeof، شما می توانید جنس یک متغیر را دریافت نمایید. در صورتی که به این دستور، نام یک تابع و یا متغیری که تابع در آن ذخیره شده است را ارسال نمایید، جنس آنرا function اعلام می کند.

ولی واقعیت این است که بهتر است، توابع را به عنوان اشیاء در نظر بگیریم.

در زبان جاوا اسکریپت، توابع می توانند Property و Method داشته باشند.

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


function myFunction(a, b) {
    return arguments.length;
}


The toString() method returns the function as a string:


در صورتی که در داخل سورس کد، بعد از نام تابع و یا متغیری که تابع را در داخل آن ذخیره کرده اید، از تابع toString استفاده نمایید، می توانید، کل قسمت مربوط به تعریف تابع را به صورت متنی بدست آورید.


function myFunction(a, b) {
    return a * b;
}

var txt = myFunction.toString();


A function defined as the property of an object, is called a method to the object.
A function designed to create new objects, is called an object constructor.


در صورتی که در داخل یک تابع، تابعی تعریف نمایید، تابع درونی Method نامیده می شود.

تابعی که برای ایجاد یک شیء، نوشته می شود، سازنده شیء نامیده می شود.


این مطلب هنوز در حال تکمیل می باشد!

مرجع: http://www.W3Schools.com

  • داریوش تصدیقی
۱۰
آبان

JavaScript Function Definitions

JavaScript functions are defined with the function keyword.


توابع جاوا اسکریپت با کلیدواژه function تعریف می شوند.


You can use a function declaration or a function expression.


شما می توانید یا از تکنیک Declaration و یا Expression برای تعاریف توابع استفاده نمایید.


Function Declarations


Functions are declared with the following syntax:

تعریف توابع به شکل ذیل را Function Declarations می گویند:

function functionName(parameters) {
  code to be executed
}

Declared functions are not executed immediately. They are "saved for later use", and will be executed later, when they are invoked (called upon).

زمانی که شما توابعی را تعریف می کنید، در همان لحظه اجرا نمی شوند. آنها صرفا برای استفاده های آتی ذخیره می گردند، زمانی اصطلاحا آنها را اجرا (Invoke) می کنید.

function myFunction(a, b) {
    return a * b;
}

Semicolons are used to separate executable JavaScript statements.
Since a function declaration is not an executable statement, it is not common to end it with a semicolon.

برای جدا کردن دستورات اجرایی جاوا اسکریپت از (;) استفاده می کنیم، ولی از آنجایی که تعریف توابع، یک دستور اجرایی محسوب نمی شود، معمولا مرسوم نیست که پس از آکولاد بسته تابع، (;) قرار دهیم.

Function Expressions

A JavaScript function can also be defined using an expression.

A function expression can be stored in a variable:

توابع می توانند به شکل Expression تعریف شوند. در این حالت (به شکل ذیل)، ما متغیری را تعریف کرده و یک تابع را به آن Assign می کنیم:


var x = function (a, b) {return a * b};


After a function expression has been stored in a variable, the variable can be used as a function:


بعد از اینکه تابع به صورت Expression تعریف گردید و ما تابع را در داخل یک متغیر (x) ذخیره کردیم، می توان از متغیر x به صورت یک تابع استفاده کرد. بدین معنی که وقتی متغیر x را فرآخوانی می کنیم، مانند این است که تابع ذخیره شده در آن را فرآخوانی می کنیم.


var x = function (a, b) {return a * b};
var z = x(43);


The function above is actually an anonymous function (a function without a name).

Functions stored in variables do not need function names. They are always invoked (called) using the variable name.

The function above ends with a semicolon because it is a part of an executable statement.

به تابعی که بدون نام، و به شکل فوق تعریف می شود، اصطلاحا Anonymous Function می گویند.

توابعی که به شکل فوق تعریف شده، و آنها را در داخل یک متغیر ذخیره می کنیم، نیازی به نام ندارند. این توابع همیشه از طریق متغیرهایی که آنها را در خود ذخیره کرده اند، اجرا (Invoke) می شوند.

دقت داشته باشید، وقتی که توابع به صورت فوق تعریف می گردند، از آنجایی که به صورت دستور اجرایی تعریف می شوند، باید پس از آکولاد بسته، (;) نوشته شود.

The Function() Constructor


As you have seen in the previous examples, JavaScript functions are defined with the function keyword.

Functions can also be defined with a built-in JavaScript function constructor called Function().


همچنانکه در مثال های قبل ملاحظه کردید، توابع جاوا اسکریپت با کلید واژه function تعریف می شوند.

توابع همچنین می توانند توسط یک تابع سازنده از پیش تعریف شده به نام ()Function نیز تعریف شوند. بدین صورت که آخرین پارامتر آن کد تابع و پارامترهای قبلی آن به عنوان پارامترهای ورودی معرفی می شوند.

var myFunction = new Function("a""b""return a * b");

var x = myFunction(43);


در مثال فوق، ما یک تابع به صورت anonymous و expression و با استفاده از تابع Function تعریف کرده ایم.


You actually don't have to use the function constructor. The example above is the same as writing:


عملا شما مجبور به استفاده از Function Constructor نمی باشید. مثال فوق دقیقا با مثال ذیل معادل می باشد:


var myFunction = function (a, b) {return a * b};

var x = myFunction(43);


Most of the time, you can avoid using the new keyword in JavaScript.


در اکثر مواقع، شما می توانید از کلید واژه new، در جاوا اسکریپت، اجتناب نمایید.


Function Hoisting

JavaScript functions can be called before they are declared:


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


myFunction(5);

function myFunction(y) {
    return y * y;
}


Functions defined using an expression are not hoisted.


دقت داشته باشید، توابعی که به صورت Expression تعریف می شوند، یعنی توابعی که در داخل یک متغیر ذخیره می گردند، نمی توانند به صورت Hoisted مورد استفاده قرار گیرند. یعنی در صورتی که تابعی را به صورت Expression تعریف کرده باشید، نمی توانید متغیر مربوط به تابع مربوطه را، قبل از محل تعریف آن، استفاده نمایید، در این حالت تابع مربوطه اجرا نخواهد شد!


Self-Invoking Functions

Function expressions can be made "self-invoking".

A self-invoking expression is invoked (started) automatically, without being called.

Function expressions will execute automatically if the expression is followed by ().

You cannot self-invoke a function declaration.

You have to add parentheses around the function to indicate that it is a function expression:


در زبان جاوا اسکریپت، می توان به گونه ای تابعی را تعریف نمود که پس از تعریف آن، به طور خودکار اجرا شود. به این دسته از توابع Self-Invoking Functions می گویند.

اینگونه توابع، بدون اینکه نیازی باشد که در خط دیگری در سورس کد، آنها را اجرا نماییم، به طور خودکار اجرا می شوند.

اگر بعد از آکولاد بسته توابع، از دو پرانتز باز و بسته () استفاده شود، این توابع به صورت Self-Invoking Function عمل می کنند.

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

(function () {
    var x = "Hello!!";      // I will invoke myself
})();


لازم به ذکر است که به توصیه Crockford، بهتر است بعد از آکولاد بسته تابع، () را نوشته و سپس تابع و () را با هم، درون یک () دیگر قرار دهید:


// Crockford Recommandation!
(function () {

    var x = "Hello!!";      // I will invoke myself
}());


The function above is actually an anonymous self-invoking function (function without name).


اصطلاحا به تابعی که به شکل فوق تعریف می شوند، Anonymous self-invoking function اطلاق می شود. دقت داشته باشید که معمولا در این حالت نام تابع نوشته نمی شود!

Functions Can Be Used as Values

JavaScript functions can be used as values:

در زبان جاوا اسکریپت، گاهی اجرای توابع، به عنوان مقدار، مورد استفاده قرار می گیرند:


function myFunction(a, b) {
    return a * b;
}

var x = myFunction(43);


JavaScript functions can be used in expressions:


و گاهی نیز، می توان در یک عبارت محاسباتی، از نتایج اجرای آنها استفاده نمود:


function myFunction(a, b) {
    return a * b;
}

var x = myFunction(43) * 2;

پایان قسمت اول... با ما باشید...

مرجع:‌ http://www.W3Schools.com

  • داریوش تصدیقی