Автор Тема: jQuery, асинхронна ajax заявка, abort()  (Прочетена 6153 пъти)

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Такам, дълго е за обяснение, затова ще бъда максимално кратък. Налага ми се да напиша един perl CGI скрипт, който да изкарва една таблица. На някои от полетата в таблицата при onmouseover трябва да се показва един tooltip. На практика, прави се една Ajax заявка, perl скрипта прави едни заявки към базата, връща каквото има да връща, javascript кода съответно показва един малоумен div с резултатите от заявката и всичко 6.

Първоначално реших да ползвам CGI::Ajax, но много бързо се отказах - това генерира малоумен javascript и е по-дървено, отколкото сам да си принтвам на ръка.

Обаче понеже все пак нямам нерви да изпращам сам въпросната заявка, така че да работи с повечето браузъри като хората, реших да ползвам някоя готова библиотека за целта - jQuery ми се видя добра идея.

И така, прекрасно - за половин час успях някак да докарам това, което искам, но остава един сериозен проблем, който ужасно много ме дразни.

Значи ако достатъчно бързо мръдна мишката върху няколко полета и я задържа над последното, настава некъв ужас, некъв ад. Всички шибани асинхронни HTTP заявки в един момент приключват изпълнението си, разбира се никой не гарантира че това става в последователността, в която са изпратени, след което викат шибаната си success callback функция и става мазало - вместо да видя това, което очаквам да видя, виждам нещо от тези полета дето съм минал с курсора на мишката върху тях.

Реших, че би било добра идея просто да викна abort() метода при onmouseout, само че изненада - това не работи.

Не знам кой ги измисля тези неща, но аз винаги съм очаквал че когато правя някаква асинхронна операция и я abort-на преди да е завършила, няма да ми се trigger-не callback функцията за успешно завършване на операцията. В смисъл ако не е така, тогава очевидно няма смисъл от  abort() защото на практика нищо не се abort-ва.


Не се занимавам с уеб разработване и честно казано почнах да се изчерпвам откъм идеи. Някой има ли идея за някакъв workaround на тая работа, защото определено дразни.
Активен

"Knowledge is power" - France is Bacon

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #1 -: Jul 12, 2010, 18:27 »
Как точно използваш abort()? По принцип имаш нужда от обект, за наличността на който да проверяваш и, ако го има, да го прекъсваш, връзвайки abort() към него. Или казано в код
Код
GeSHi (Javascript):
  1. if (myObject.readyState != 0) {
  2.     myObject.abort();
  3. }
  4. myObject = $.ajax({
  5.    type: "POST",
  6.    url: "some.cgi",
  7.    data: "&some=data",
  8.    success: function(msg){
  9.       $('#div_id').html(msg);
  10.    }
  11. });
И би трябвало да работи.
« Последна редакция: Jul 12, 2010, 18:29 от neter »
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #2 -: Jul 12, 2010, 19:03 »
Имам един <div> на който success функцията променя CSS свойствата и променя innerHTML в зависимост от това, което му върне скрипта. Проблемът е че success callback-а се вика в момента в който някоя от ajax заявките приключи, та мислих да викам в момента в който курсора напусне полето, нещо от сорта на onmouseout="myObject.abort()".

Оказва се че с jQuery 1.3.2 това работи и след abort(), success не се извиква , но с 1.4.x - не.

Както и да е, сега ползвам 1.3.2 и нямам този проблем...обаче поради някаква причина сега (субективно погледнато) ajax заявките са по-бавни, не знам защо. Освен което кеширането се чупи за firefox (странно обаче работи за IE) - това също е необяснимо, с 1.4 работеше и при двата браузъра. Хубавото е че не ми пука, защото идеята е да работи за IE, за други браузъри - ако работи би било добре, но не ми е задължително.
Активен

"Knowledge is power" - France is Bacon

victim70

  • Напреднали
  • *****
  • Публикации: 454
  • Distribution: Gentoo, Ubuntu
  • Window Manager: Kde Xfce
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #3 -: Jul 12, 2010, 21:50 »
//off
Колеги а от къде може да се по прочете за това чудо Ajax. Искам препоръки като за абсолютно начинаещ. Не първите гугълски връзки.
Активен

"Господи, дай ми сила да променя нещата които немога да приема,
дай ми търпение да приема нещата които не мога да променя,
и ми дай мъдрост, да правя разликата между двете"

BULFON

  • Administrator
  • Напреднали
  • *****
  • Публикации: 478
  • Distribution: Fedora
  • Window Manager: Gnome
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #4 -: Jul 12, 2010, 22:41 »
В случая зад ajax не се крие нито сложни математически модели, нито особени технически "врътки". Това е име на технология, което някой измисли, защото е по-лесно за ползване, а и е по бизнес звучащо. Останалото са подробности.
Накратко, Microsoft, в IE4 предоставят API за изпълнение на HTTP заявки. Нещо, което така или иначе браузера прави. Тези заявки изглеждат точно като заявка от същият браузър - пращат същите кукита, и при получаване на такива ги установяват. С такава функционалност създателят на една страница може да си определи някакво първоначално съдържание, към което да добави още в последствие с допълнителни заявки към сървъра. За сигурност не са позволени заявки към сървър различен от този, който е пратил оригиналната страница.
Това API в последствие е вградено в абсолютно всички браузъри.
За всичко което изредих има и заобиколни решения и унифициран интерфейс във всяка Javascript библиотека.
Затова най-добре подходи като gat3way - ползвай jQuery и неговите AJAX функции. Така е най-лесно.
Успех!
Активен

фонокартен телефонен апарат

betso

  • Напреднали
  • *****
  • Публикации: 281
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #5 -: Jul 13, 2010, 00:42 »
Не разбирам нито от perl, нито особено от jQuery, но реших да попитам, какъв е проблема на следното решение:
Код
GeSHi (Javascript):
  1. <?php
  2. if ($_GET['action'] == 'td1') {
  3. echo 'This is the content of the first cell.';
  4. } else if ($_GET['action'] == 'td2') {
  5. echo 'Това е съдържанието на втората клетка.';
  6. } else if ($_GET['action'] == 'td3') {
  7. echo '!?';
  8. } else { ?>
  9. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  10. <html>
  11. <head>
  12. <title>hover Table</title>
  13. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  14. <script language="JavaScript" type="text/javascript">
  15. function ahah(url,target) {
  16. document.getElementById(target).innerHTML='Loading...';
  17. if(window.XMLHttpRequest) { req=new XMLHttpRequest(); }
  18. else if(window.ActiveXObject) { req=new ActiveXObject("Microsoft.XMLHTTP"); }
  19. if(req!=undefined) {
  20. req.onreadystatechange=function() { ahahDone(url,target); };
  21. req.open("GET",url,true);req.send("");
  22. }
  23. }
  24.  
  25. function ahahDone(url,target) {
  26. if(req.readyState==4) {
  27. if(req.status==200) { document.getElementById(target).innerHTML=req.responseText; }
  28. else { document.getElementById(target).innerHTML=" Error:\n"+req.status+"\n"+req.statusText; }
  29. }
  30. }
  31.  
  32. function load(name,div) {
  33. ahah(name,div);
  34. return false;
  35. }
  36. </script>
  37. <style type="text/css">
  38. td.tip {
  39. position: relative;
  40. text-decoration: none;
  41. }
  42. td.tip span {
  43. display: none;
  44. position: absolute;
  45. top: 30px;
  46. left: 10px;
  47. width: 150px;
  48. padding: 5px;
  49. z-index: 100;
  50. background: #eeeeee;
  51. color: #112233;
  52. font: normal 8pt Helvetica,Arial;
  53. text-align: left;
  54. }
  55. td:hover.tip { font-size: 99%; }
  56. td:hover.tip span { display: block; }
  57. </style>
  58. </head>
  59. <body>
  60. <table>
  61. <tr>
  62. <td class="tip" onmouseover="load('<?=$_SERVER['PHP_SELF'];?>?action=td1', 'td1'); return false;">1<span id="td1"></span></td>
  63. <td class="tip" onmouseover="load('<?=$_SERVER['PHP_SELF'];?>?action=td2', 'td2'); return false;">2<span id="td2"></span></td>
  64. <td class="tip" onmouseover="load('<?=$_SERVER['PHP_SELF'];?>?action=td3', 'td3'); return false;">3<span id="td3"></span></td>
  65. </tr>
  66. </table>
  67. </body>
  68. </html>
  69. <? }
  70. exit; ?>

//off
Колеги а от къде може да се по прочете за това чудо Ajax. Искам препоръки като за абсолютно начинаещ. Не първите гугълски връзки.
През далечната 2005 излезе една кратка статийка с демонтрация на подобни заявки: "Rasmus' 30 second AJAX Tutorial". Тогава се заинтригувах по подобни решения, но (най-вече поради липса на време) не успях да изляза от простите решения и да вникна в използването на истинските и разпространени AJAX-библиотеки, като jQuery, Prototype, Script.aculo.us или MooTools. Попаднах обаче на SimpleJS, в което се опитах да вникна и да го разбера. Метни му един поглед, след като разгледаш примера на Rasmus. На мен ми помогна и ми даде възможност да разбера, как да си напиша прости функции, които да ми вършат работа. Успех! :)
« Последна редакция: Jul 13, 2010, 00:45 от betso »
Активен

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #6 -: Jul 13, 2010, 01:28 »
Оказва се че с jQuery 1.3.2 това работи и след abort(), success не се извиква , но с 1.4.x - не.
А, виж ти! Това не е нормално просто да махнат възможността за прекратяване на заявки, направени с .ajax(). Предполагам, че е заменено с нещо по-специфично за функцията .ajax(), вместо да се ползва общият .abort(), обаче засега не откривам с какво.
Както и да е, оказва се, че .abort() действа с функциите .get() и .post() и в 1.4.2, така че можеш да ползваш тях:
Код
GeSHi (Javascript):
  1. $('#cell_id').mouseover(function(){
  2.     myObject = $.get('some.cgi', {'get_key': 'get_value'}, function(content){
  3.          $('#result_id').html(content);
  4.     });
  5. });
  6.  
  7. $('#cell_id').mouseout(function(){
  8.     myObject.abort();
  9.     $('#result_id').html('');
  10. });
По същия начин и за .post(), само се заменя името на функцията. Специфичното при .post() е, че заявките с тази функция не се кешират, така че трябва да се има в предвид дали е предимство или недостатък в конкретния случай.

betso, при писане на чист javascript се налага да се съобразяваш с различни правила според браузърите, а и изисква изписването на повече код. Целта на jQuery е да предложи кратък синтаксис за иначе дълъг код, и едновременно с това добра съвместимост с различните браузъри. Едновременно с това (характерно за всеки framework) програмистите се слагат в стилова рамка, която трябва да спазват, с което се постига унифициране на кода, а от там и по-лесното му четене от други хора. Естествено, с чистия javascript може да се напишат повече неща, отколкото с jQuery - все пак jQuery е писан на javascript, но (въпреки че се цели) не съдържа в себе си цялата функционалност на javascript. Но кодът, изписан на чист javascipt, често е разхвърлян, поради пълната свобода на програмиста да си пише в каквито си иска стилове, чете се по-трудно, и изисква изписване на много неща, които в jQuery са автоматизирани. Когато се пише нещо малко, не е особен проблем да се ползва чист javascript (даже е за предпочитане в доста случаи), но при големи проекти ползването на framework вече не е препоръчително, а задължително, иначе представи си каква лудница от стилове на изписване на кода ще се наблюдава в тези проекти, при положение, че (най-често) не го изписва само един човек, а (най-често) ще се наложи този код да се чете и от други хора след това ;)

P.S.: Забравих да вметна, че в горния пример използвах задаване на точно определено id на елемента, който се посочва, но (както и в случая ще се наложи, за да не се изписва всичко за всеки елемент от таблицата) може да се зададе директно типа на елемента, а id-то на елемента може да се праща като променлива към зареденото url:
Код
GeSHi (Javascript):
  1. $('td').mouseover(function(){
  2.     currentid = $(this).attr('id');
  3.     myObject = $.post('some.cgi', {'post_key': currentid}, function(content){
  4.          $('#result_id').html(content);
  5.     });
  6. });
  7.  
  8. $('td').mouseout(function(){
  9.     myObject.abort();
  10.     $('#result_id').html('');
  11. });
« Последна редакция: Jul 13, 2010, 02:36 от neter »
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

betso

  • Напреднали
  • *****
  • Публикации: 281
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #7 -: Jul 13, 2010, 02:10 »
neter, аз разбирам смисъла на frameworks. И той е същият не само за JavaScript, а и за други езици. Просто исках да разбера, дали в случая се използва jQuery, защото е най-прекият път или от съображенията, които ти изложи. И понеже ми хрумна горното кратко решение (работещо на няколкото браузера, на които го тествах), си помислих да попитам, дали пък аз не бъркам някъде в предположението, че то ще работи без да се товари трафика с допълнителна библиотека. Макар че признавам, 20-ината КБ на jQuery (в компресиран формат) не са проблем.
Благодаря за мнението! :)
Активен

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #8 -: Jul 13, 2010, 03:06 »
О, не! Това не ми е мнението. Помислих, че питаш за причините да се ползва framework по принцип :) Мнението ми е, че предложението, което даваш, е реално приложимият метод при използване на чист javascript, така че това е решението за малки задачки. И, тъй като в случая става дума за скрипт, а не за цялостен проект, няма нищо лошо gat3way да се спре на твоето решение.
Просто въпросът беше зададен за jQuery, а и на мен все по-малко ми се пише в чист javascript. Само да го нямаше мързелът да си пренапиша всички досегашни писания от чист javascript на jQuery... ::)
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #9 -: Jul 13, 2010, 10:10 »
Код:
<td class="tip" onmouseover="load('<?=$_SERVER['PHP_SELF'];?>?action=td1', 'td1'); return false;">1<span id="td1"></span></td>

Как ми липсва това, не е истина. В проклетия perl не можеш да си отваряш тагове с perl-ски код - или принтваш html-а от скрипта/ползваш CGI модула, което често е доволно неудобно (вече спрях да го ползвам за нещо друго освен принтване на хедъра, това примерно ако искаш да ти направи таблица е ебати мъчението), или ползваш темплейти - тоя модел на работа също не ми допада, много пипкава работа е.

jQuery ползвам именно защото не ми е работа да се занимавам с уеб-работи и много вероятно ще ги оплескам нещата. Тези проверки за браузъри (примерно activexobject vs xmlhttprequest) ми ходят по нервите и реших, че с jQuery ще си ги спестя. Освен това, jQuery наистина е много лесно за ползване. От друга страна, все пак не че си спестих проверките за браузъри - примерно тъпия IE има друга идея за абсолютните координати, в зависимост от позицията на скролбара на документа, доволно дразнещо.

Както и да е, оказва се че това си е проблем в jQuery и хората са си пуснали ticket, но още не е оправено - http://forum.jquery.com/topic/after-aborting-an-ajax-call-success-event-is-still-being-fired

Активен

"Knowledge is power" - France is Bacon

VladSun

  • Moderator
  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #10 -: Jul 13, 2010, 10:13 »
Код
GeSHi ():
  1. <td class="tip" onmouseover="load('<?=$_SERVER['PHP_SELF'];?>?action=td1', 'td1'); return false;">1<span id="td1"></span></td>


echo $_SERVER['PHP_SELF']    =>  XSS ;)
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

VladSun

  • Moderator
  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #11 -: Jul 13, 2010, 10:17 »
... да се товари трафика с допълнителна библиотека. Макар че признавам, 20-ината КБ на jQuery (в компресиран формат) не са проблем.

Имаше един сайт (не помня кой точно беше), в който има качени и свободни за сваляне много подобни библиотеки (и други ресурси) с цел да се използва кеша на браузера на отделните клиенти (т.е. да се повиши вероятността този ресурс да го има в кеша).
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

gat3way

  • Напреднали
  • *****
  • Публикации: 6050
  • Relentless troll
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #12 -: Jul 13, 2010, 10:38 »
Библиотеката не е голям проблем, това е интранетско приложение така или иначе. Освен което предполагам че браузърите кешират js файла след като са го заредили веднъж.

Кеширането при ajax завките е малко по-важно, защото отнемат известно време (server-side скрипта прави заявки към база). Не работи в FF де, но при IE се държи доста културно :)
Активен

"Knowledge is power" - France is Bacon

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #13 -: Jul 13, 2010, 11:04 »
Щом имаш нужда от кеширане, ползвай .get() функцията, докато оправят .abort()-a за .ajax(), ако мислиш да останеш с 1.4.2 (по-добре). Сработва във всички браузъри, които пробвах, и ще пази кеш на заявките. За кое казваш, че не работи във FF, но в IE работи?
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

VladSun

  • Moderator
  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: jQuery, асинхронна ajax заявка, abort()
« Отговор #14 -: Jul 13, 2010, 12:07 »
Проблемът с кеширането се решава елементарно с добавяне на уникална стойност към URL-а (прим. текущото време в ms)

Код
GeSHi (Javascript):
  1. var url = "http://localhost/index.php?arg=value&nocache=" + (new Date()).getTime();
  2.  

EDIT: Опа, ти обратното искаш :(
« Последна редакция: Jul 13, 2010, 12:08 от VladSun »
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Scsi abort operation проблем
Настройка на хардуер
halturata 2 2087 Последна публикация Sep 04, 2007, 15:45
от halturata
малко помощ с jquery
Web development
madmad 1 1725 Последна публикация Dec 18, 2010, 22:48
от neter
jquery datepicker да се зареди от трети файл
Web development
nov_chovek 6 2993 Последна публикация Jan 22, 2011, 21:18
от nov_chovek
jQuery, ajax, странни работи :)
Web development
gat3way 2 2729 Последна публикация Mar 25, 2011, 23:47
от gat3way
Тест за jQuery & Ajax. Защо фейлва на Хром?
Web development
clovenhoof 10 4226 Последна публикация Jun 05, 2013, 18:19
от clovenhoof