1. مهمان گرامی، جهت ارسال پست، دانلود و سایر امکانات ویژه کاربران عضو، ثبت نام کنید.
    بستن اطلاعیه

آموزش مفاهیم Ajax با دلفی

شروع موضوع توسط hector2141 ‏11/9/12 در انجمن Delphi

  1. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,326
    تشکر شده:
    2,655
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پیشنیاز این مقاله :

    بلد بودن مفاهیم ابتدایی برنامه نویسی تحت وب
    بلد بودن Html به مقدار کافی
    کمی JavaScript
    کمی XML

    ضمنا اینایی که اینجا میگم فرقی نداره از چه زبان برنامه نویسی استفاده بشه اما برای مثالهام فعلا از دلفی 7 و WebSnap استفاده میکنم .

    بسم الله

    سناریو :
    فرض کنید یک سایت خوشگل طراحی کریدین با کلی عکس و جدول و این حرفها ، یک گوشه سایت هم دوتا TextBox گذاشتین با یک دکمه برای Login . وقتی کاربر کد کاربری و کلمه عبورش رو وارد میکنه و دکمه ورود رو میزنه اطلاعات نوشته شده برای سرور فرستاده میشوند و سرور تصمیم میگیره که اگر اطلاعات درست هست صفحه بعد رو برای کاربر ایجاد کنه و بفرسته ، اما اگر اطلاعات غلط بود باید دوباره همون صفحه قبلی رو بسازه و دوباره کاربر تمام اون صفحه رو لود کنه (حالا بحث کش کردن بماند) با این فرق که این دفعه فقط یک گوشه ای بنویسه مثلا "کد کاربری غلط است". فکرش رو بکنید یکبار تمامی کانتت قیلدهای صفحه برای سرور فرستاده شده ، و یکبار هم کل صفحه دوباره جنریت شده آخر هم یوزر مجبور شده همه صفحه رو دوباره بگیره.
    چقدر خوب میشد اگر بدون دست زدن به بقیه صفحه فقط کدکاربری و پسورد برای سرور فرستاده میشد و سرور هم فقط میگفت درسته یا نه ![​IMG]
    فکر میکنین میشه ؟

    خب معلومه دیگه اگر نمیشد که این قصه رو تعریف نمیکردم . طبیعتا هم با AJAX میشه دیگه ;)

    AJAX
    آژاکس که مخفف Asynchronous JavaScript And XML هست و شاید اینطوری بشه ترجمش کرد که یعنی استفاده نامتقارن از جاوا اسکریپت و XML ، ذاتا چیزه جدیدی نیست و خیلی وقت هست که تقریبا هر آنچه رو که برای کار کردن باهاش لازم هست فراهم شده اما نامگذاریش و اینکه یکهو اینقدر محبوب بشه شاید 2 سال نیست که باب شده.
    به هر حال اصل کار رو آبجکت XMLHttpRequest انجام میده که مایکروسافت نوشتتش و کار این آبجکت اینه که یک اربتاط مجزا با سرور برقرار کنه یکسری اطلاعات رو بفرسته و نتیجه رو از سرور بگیره ، همونطوری که میدونید بهترین روشی که بشر برای تبادل اطلاعاتی که Structorشون از قبل معلوم نیست ، اختراع کرده XML هست پس وقتی این آبجکت بتونه XML بگیره و بفرسته پس میتونه هر اطلاعاتی با هر ساختاری رو بگیره و بفرسته ، اما لزومی هم نداره حالا حتما از XML استفاده کنیم همونطوری که ما فعلا برای اول کار از Text ساده استفاده میکنیم و تازه برای اولین مثال هم بیخیال نامتقارن بودنش میشیم :

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

    از اینجا ببعد من با دلفی شروع میکنم ، اما مثلا شما هم میتونید با ASP شروع کنید ولی به هر حال هیچ فرقی نداره از چه زبانی استفاده میکنید :

    دلفی رو باز کنید ، New>Web Server Application (اون پاییناست) بعد هم Cgi-StandAlone رو انتخاب کنید .

    یک وب ماژول براتون ساخته میشه، این اون سرور وب ما هست ; یک جای خوشگل Save بکنیدش ، بعد هم برید توی IIS (بله IIS برنامه تحت وب دارین مینویسین دیگه ) یک VirtualDicrectory رو به نام مثلا AJAXTest بسازید و بهش مربوط کنید .(دسترسی Execute رو هم روش بدین) (لطفا دات نتی ها فکر نکنن که اونا خیلی بهشون خوش میگذره و از این حرفها ندارند، توی دلفی هم ما با اینتراوب وب سرور خودمون رو داریم که خیلی هم از Casini شما بهتره ;) )
    خب بریم خدمت جناب دلفی : روی وب ماژول کلیک راست بکنید بعد هم ActionEditor و یک Action جدید ایجاد بکنید ،
    اسمش رو مثلا بزارید actStart و PathInfo رو هم به /Start ست بکنید. بعد یکدونه PageProducer از تب اینترنت روی فرم بزارید اسمش رو بزارید ppStart و در اکشن ادیتور دیتا ماژول Producer اکشنی که تعریف کردید رو بزارید همین PageProducer. (معنی این کار این هست که هر موقع این اکشن صدا زده بشه این Producer وظیفه تولید HTML پاسخ رو داره).
    این شد اکشنی که قرار صفحه ابتدایی رو تولید کنه ، یک اکشن هم میخواهیم که جواب درخواست آژاکسیمون رو بده ، پس یک اکشن دیگه درست میکنیم اسمش رو میزاریم مثلا GetDay نیازی هم به PageProucer نداره .
    حالا بریم توی ppStart کدهای HTML لازم برای تولید صفحه رو بنویسیم :
    اول از همه باید یک XMLHttpRequest بسازیم که بتونی اطلاعات رو برامون درخواست کنه ، من ساختن XMLHttpRequest و درخواست اطلاعات رو توی یک تابع مینویسم و بعد توضیحش میدم :
    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    [/TD]
    [TD="class: code"]function requestDay()
    {
    if (window.XMLHttpRequest)
    {
    var Rqst = new XMLHttpRequest();
    }
    else
    {
    var Rqst = new ActiveXObject("Microsoft.XMLHttp");

    }
    var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
    Rqst.open('GET', reqUrl, false);
    Rqst.Send('');
    document.getElementById("txtDay").value = Rqst.responseText;
    }

    [/TD]
    [/TR]
    [/TABLE]



    توی چند خط اول سعی میکنیم آبجکت XMLHttpRequest رو بسازیم -چه برای اینترنت اکسپلور ، چه فایرفاکس و کلا رفقای موزیلا- بعد هم چون توی این مثال اول میخوایم از متد Get استفاده کنیم ، باید پارامترهامون رو توی URL بفرستیم پس ، یک URL میسازیم که شامل آدرسی که باید بهش مراجه کنیم هست که میشه همون مراجعه به اکشن GetDayی که درست کردیم بعد علامت ؟ که به این معنیه که از اینجا ببعد میخوای پارامتر بفرستیم بعد اسم پارامترمون که من گذاشتم day و بعد هم مقدار پارامتر که از یک TextBox که توی HTMLمون بعدا درست میکنیم و اسمش رو میزاریم txtDay گرفته میشه.
    یعنی زمان اجرا مثلا مقدار پارامتر همچین چیزی (اگر کاربر توی TextBox مقدار 5 رو بنویسه) میشه :
    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    [/TD]
    [TD="class: code"]getday?day=5

    [/TD]
    [/TR]
    [/TABLE]




    بعد هم میریم سراغ آبجکت XMLHttpRequest که ایجادش کردیم و توی متغیر Rqst داریمش و متد Open رو که صدا میکنیم تا کانکشنش رو با سرور برقرار کنه ، برای متد Open باید 3 تا پارامتر پاس کنیم ، اولی متد ارسال اطلاعات هست که توی این مثال ما از Get استفاده میکنیم ، دومی آدرس سرور هست و سومی اینکه آیا بصورت نامتقارن درخواست صورت بگیره یا خیر (بعدا کاملا توضیحش میدم ) ، ولی فعلا پارامتر سوم را false پاس میکنیم به معنی اینکه متقارن با سرور در ارتباط هستیم .
    بعد هم متد Send رو صدا میزنیم با پارامتر خالی تا درخواست صورت بگیره در صورتیکه از متد Post استفاده میکردیم پارامترها رو اینجا پاس میکردیم .(انشاا.. جتما یک متد پست هم مثال میزنم)
    در نهایت هم نتیجه برگشته از سرور رو توی همون TextBoxی که کاربر توش عدد رو وارد کرده بر میگردونیم.

    تا اینجا هستیم کل HTML لازم برای صفحه اول رو کامل کنیم ، باید در نهایت توی ppStart داخل HTMLDocument این متن رو داشته باشیم :

    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    [/TD]
    [TD="class: code"]<html>
    <head>
    <Script Language="JavaScript">
    function requestDay()
    {
    if (window.XMLHttpRequest)
    {
    var Rqst = new XMLHttpRequest();
    }
    else
    {
    var Rqst = new ActiveXObject("Microsoft.XMLHttp");

    }
    var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
    Rqst.open('GET', reqUrl, false);
    Rqst.Send('');
    document.getElementById("txtDay").value = Rqst.responseText;
    }

    </Script>
    </head>
    <body>
    <Table>
    <tr>
    <td Align="right"> The Day No: </td>

    <td>
    <input type="text" id = "txtDay"></td>
    <td><input type="Button" onclick= "requestDay();" value = "Get Day" ></td>
    </tr>
    </Table>
    </body>
    </html>

    [/TD]
    [/TR]
    [/TABLE]




    در واقع تگهای مورد نیاز HTML و همینطور اون TextBox رو داخل یک Table گذاشتیم ، بعلاوه یک Button که روی OnClickش همون تایعی که نوشتیم رو صدا میزنیم.

    خب قسمتهای کلاینت سایدمون تموم شد ، میمونه نوشتن کد دلفی سرور که قرار هست به این درخواستها جواب بده :
    اکشن GetDay رو انتخاب کنید و توی ایونت هاش OnAction رو انتخاب کنید ، این رخداد زمانی Fire میشه که یک Request برای این اکشن فرستاده میشه ، یعنی دقیقا وقتی که ما با اون XMLHttpRequest میایم سراغ این اکشن getday ، حالا توی کد دلفی مثلا میتونیم این کد رو بنویسیم :

    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [/TD]
    [TD="class: code"]procedure TwbmdlAjax.wbmdlAjaxactGetDayAction(Sender: TObject;
    Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
    var
    ADay : Integer;
    AResult: String;
    begin
    ADay := StrToInt(Request.QueryFields.Values['day']);
    case ADay of
    1: AResult := 'Sat';
    2: AResult := 'Sun';
    3: AResult := 'Mon';
    4: AResult := 'Tue';
    5: AResult := 'Wed';
    6: AResult := 'Thu';
    7: AResult := 'Fri'
    else AResult := 'Invalid Day No : ' + IntToStr(ADay);
    end;

    Response.Content := AResult;
    end;

    [/TD]
    [/TR]
    [/TABLE]




    فکر میکنم کدمون واضح هست دیگه ، مقار پارامتر Day رو از Request میگیریم ، بعد هم توی Case معادل روز هفته رو بر میگردونیم و نهایتا هم نتیجه رو در Content جوابمون میزایم.

    * در مورد actStart که این کار رو نکردیم و بجاش به یک PageProducer وصلش کردیم ، محتوای PageProducer بعنوان پاسخ فرستاده میشه.

    * برای اونایی که زیاد با Websnap آشنایی ندارند : Request آبجکتیه که همه اطلاعات مربوط به درخواست توش هست و Response آبجکتیه که اطلاعات مربوط به پاسخی که قرار فرستاده بشه توش قرار میگیره

    دیگه مثالمون آمادست ، حالا یک بروسر باز میکنیم (مثلا IE) و این رو در آدرسش مینویسیم :
    (من پروژه رو بنام BasicAjax دخیره کردم)

    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    [/TD]
    [TD="class: code"]http://localhost/Ajaxtest/BasicAjax.exe/Start


    [/TD]
    [/TR]
    [/TABLE]




    وقتی که صفحه اولمون اومد توش مثلا عدد 5 رو مینویسیم و دکمه Get Day رو فشار میدیم . دقت کنید که برعکس اکثر صفحاتی که تا بحال در وب دیده اید کل صفحه Refresh نمیشه و اصلا Refreshی در کار نیست ، فقط مقدار جواب در TextBox قرار میگیره.
     
  2. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,326
    تشکر شده:
    2,655
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    پاسخ : آموزش مفاهیم Ajax با دلفی

    ارسال نامتقارن اطلاعات

    این نا متقارن اصلا یعنی چی ؟ چه فایده ای داره ؟! تو یک مثال ساده جفتشون رو جواب بدیم :

    برگردیم توی دلفی رو اکشن GetDay مون اولش این یک خط رو اضافه کنیم :

    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [/TD]
    [TD="class: code"]...

    <b> Sleep(5000);</b>

    case ADay of
    1: AResult := 'Sat';
    2: AResult := 'Sun';
    3: AResult := 'Mon';
    ...

    [/TD]
    [/TR]
    [/TABLE]




    این کد فقط در ارسال جواب 5 ثانیه تاخیر ایجاد میکنه ...
    حالا دوباره برنامه رو کامپایل کنید بعد هم اجرا کنید ،
    این بار که دکمه رو میزنید میبینید که کل صفحه 5 ثانیه قفل میشه و هیچ کار دیگه ای هم نمیشه کرد ، در واقع ترد IE منتظر که نتیجه Request فرستاده شده از سرور برسه و بعد به بقیه کارهاش رسیدگی کنه .
    حالا این 5 ثانیه ای که ما گذاشتیم که برای تست بود ولی ممکنه شما یک Request ارسال کنید که مثلا بره تو دیتابیس جستجو کنه و تبعد هم روی نتایج کلی پروسس انجام بده که چندین ثانیه یا حتی دقیق وقت بگیره ، اینجاست که خیلی جالب میشه اگر تا نتیحه Request ما میاد کاربر بتونه به بقیه کارهاش برسه و هر موقعه هم جواب اومد اونو نشون بده.نا متقارن فرستادن Request عملا یعنی همین !
    اما روش کار چه جوریه ؟ اولین چیزی که به ذهنمون میرسه اینه که باید پارامتر نامتقارن بودن Request رو True پاس کنیم ، خب خسته نباشید p: ;) به سرور هم که نباید دست بزنیم چون اونکه داره کار خودش رو میکنه ، پس چی میمونه ؟

    اون کد تابع requestDay رو ندوباره گاه بکنید :

    تا تیکه Request.Send() که در حالت نامتقارن هم برای ما فرقی نداره و همه چیز خوبه ، اما از اینجا به بعد که جواب میاد مشکل پیدا میکنیم ، مشکل اینه که ما نمیخواهیم صبر کنیم تا جواب بیاد بعد بقیه کد رو اجرا کنیم ، ما میخوایم هر موقع که جواب اومد بقیه کد اجرا بشه ، و چون در Browser ها ما نمیتونیم MultiThread داشته باشیم پس بقیه کد رو هم باید ترد اصلی برنامه اجرا کنیم ، پس تنها راهی که برامون میمونه ، استفاده از Event ها هست ; آبجکت XMLHttpRequest یک ایونت onreadystatechange داره که هر موقع وضعیت این آبجکت عوض بشه صدا زده میشه و مقدار ReadyState در هز زمان وضعیت آبجکت رو نشون میده که مقدار 4 به معنی کامل شدن Request و دریافت شدن اطلاعات هست پس کافیه ما ایونت onreadystatechange رو بنویسیم و هرموقع که اطلاعات گرفته شد کارمون رو انجام بدیم ، کدش میشه اینطوری :
    [TABLE]
    [TR]
    [TD="class: gutter"]1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    [/TD]
    [TD="class: code"] function requestDay()
    {
    if (window.XMLHttpRequest)
    {
    var Rqst = new XMLHttpRequest();
    }
    else
    {
    var Rqst = new ActiveXObject("Microsoft.XMLHttp");

    }
    var reqUrl = 'getday?day=' + document.getElementById("txtDay").value;
    <b>Rqst.open('GET', reqUrl, true);
    Rqst.onreadystatechange = showData;</b>

    Rqst.Send('');
    }

    <b> function showData()
    {
    if(Rqst.readyState == 4)
    if(Rqst.status == 200)
    document.getElementById("txtDay").value = Rqst.responseText;
    }</b>

    [/TD]
    [/TR]
    [/TABLE]




    توی کد بالا قبل از ارسال درخواست ایونت onreadystatechange رو ست کردیم که با هر تغییر Stateی صدا زده بشه ، همینطور مقدار پارامتر Asynchrono رو هم true کردیم که درخواست بصورت غیر متقارن فرستاده بشه ، بعد یک تابع بنام showData نوشتیم که چک میکنه هرموقع در ReadyState کامل شده (Complete) بودیم کد رو اجرا کنه ، اون چک کردن Status در ریکوست هم یک کار استاندارد هست که بر میگرده به پاسخهای Http که 200 که همون معادل OK هست به معنی درست دریافت شدن پاسخ هست . این بار که کد رو اجرا کنید و دکمه رو بزنید همون 5 ثانیه برای گرفتن جواب طول میکشه اما میبینید که توی Browser هیچ چیزی قفل نشده و کاربر میتونه به کارش ادامه بده....