RSS

Wykorzystaj asynchronizm JavaScript

Liczba odsłon: 140

Jedną z cha­rak­te­rys­tycz­nych cech ję­zy­ka Java­Script sto­so­wa­ne­go w no­wo­czes­nych apli­kac­jach klient-ser­wer jest wy­so­ki po­ziom asyn­chro­niz­mu. Choć ma­szy­na wir­tu­al­na Java­Script ob­słu­gu­je wie­lo­wąt­ko­wość w bar­dzo ogra­ni­czo­nym za­kre­sie, nie­któ­re me­cha­niz­my klu­czo­we z punk­tu wi­dze­nia reali­zac­ji no­wo­czes­nych inter­fej­sów użyt­kow­ni­ka wy­ko­rzy­stu­ją­cych AJAX rea­li­zu­ją swo­je dzia­ła­nia w tle i wy­wo­łu­ją funk­to­ry ob­słu­gu­ją­ce efek­ty żą­dań cał­ko­wi­cie asyn­chro­nicz­nie. Dla pro­gra­mis­ty Java­Script jest za­tem bar­dzo istot­ne, by nie tyl­ko ro­zu­miał i opa­no­wał asyn­chro­nicz­ne wy­wo­ła­nia funk­cji, ale wręcz wplótł asyn­chro­nizm w swój mo­del pro­jek­to­wa­nia opro­gra­mo­wa­nia.

Wyobraź­my so­bie, że bo­ga­ty zle­ce­nio­daw­ca zle­cił nam na­pi­sa­nie mo­du­łu, któ­ry po­tra­fi do­da­wać dwie licz­by. Funkcjo­nal­ność ta ma być uru­cha­mia­na przez wy­wo­ła­nie funk­cji Java­Script. Nic prost­sze­go, pi­sze­my za­tem:

function sum(a, b) {
   return a + b;
}

Oczywiś­cie, funk­cja ta bę­dzie dzia­łać do­sko­na­le:

console.log(sum(10, 20));

Z ra­doś­cią od­da­je­my go­to­wy pro­gram i już li­czy­my w my­ślach zys­ki, gdy znaj­du­je­my w skrzyn­ce pocz­to­wej no­we, zmie­nio­ne wy­mo­gi pro­jek­to­we. Usługa do­da­wa­nia ma być wciąż uru­cha­mia­na z po­zio­mu pro­gra­mu Java­Script, jed­nak sa­mo do­da­wa­nie mu­si być rea­li­zo­wa­ne na ser­we­rze. Odpowied­nia funkcjo­nal­ność po stro­nie ser­we­ra jest już za­im­ple­men­to­wa­na, wy­star­czy za­tem wy­ge­ne­ro­wać od­po­wied­nie za­py­ta­nie REST

W tym mo­men­cie uświa­da­mia­my so­bie, że przy ko­rzy­sta­niu z AJAX nie wia­do­mo, kie­dy na­dej­dzie wy­nik. Próba uży­cia in­struk­cji return jest z gó­ry ska­za­na na nie­po­wo­dze­nie.

Cofamy się w cza­sie bo­gat­si o do­świad­cze­nia i znów przy­stę­pu­je­my do im­ple­men­to­wa­nia pierw­szej wer­sji wy­ma­gań. Tym ra­zem jed­nak za­kła­da­my, że asyn­chro­nizm ma być wbu­do­wa­ny bez­po­śred­nio w pro­jekt. Staramy się też wy­ko­rzys­tać wzo­rzec pro­jek­to­wy po­le­ce­nia i za­szyć wszyst­kie in­for­mac­je – skład­ni­ki do­da­wa­nia oraz in­for­mac­ję co zro­bić z wy­ni­kiem – w obiek­cie prze­ka­zy­wa­nym do funk­cji:

function sum(request) {
   if (request.success) request.success(request.a + request.b);
}

Urucho­mie­nie ta­kiej ope­rac­ji jest nie­co bar­dziej skom­pli­ko­wa­ne i wy­ma­ga nie­ste­ty nie­co więk­szej iloś­ci ko­du źród­ło­we­go:

sum({
   a: 10,
   b: 20,
   success: function(result) {
      console.log(result);
   }
});

Jednak gdy na­dej­dą zmie­nio­ne wy­ma­ga­nia, uśmiech­nie­my się tyl­ko i zmie­ni­my im­ple­men­tac­ję funk­cji sum() na przy­kład na:

function sum(request) {
   if (request.success) $.ajax(
      'http://www.example.com/sum/?a=' + request.a + '&b=' + request.b, {
      success: function(data) {
         request.success(parseFloat(data));
      }
   });
}

Nie trze­ba bę­dzie na­to­miast w ogó­le zmie­niać ko­du w miej­scach, w któ­rych funk­cja sum() zo­sta­ła wy­wo­ła­na, gdyż pierw­sza im­ple­men­tac­ja od ra­zu uwzględ­nia­ła asyn­chro­nizm zbęd­ny co praw­da w prze­twa­rza­niu lo­kal­nym, nie­zbęd­ny jed­nak je­że­li wy­ko­rzys­tu­je się me­cha­niz­my AJAX.

Powyższy przy­kład nie ozna­cza oczy­wiś­cie, że na­wet tak pros­te funk­cje na­le­ży im­ple­men­to­wać w spo­sób asyn­chro­nicz­ny. Wręcz prze­ciw­nie, ope­rac­je co do któ­rych wie­my, że na pew­no bę­dą rea­li­zo­wa­ne lo­kal­nie i ma­ją­ce cha­rak­ter funk­cji ma­te­ma­tycz­nych na­le­ży za­pi­sy­wać ja­ko zwyk­łe funk­cje ję­zy­ka Java­Script, zwra­ca­ją­ce wy­nik za po­mo­cą in­struk­cji return. Jeżeli jed­nak two­rzy się mo­duł, któ­ry mo­że kie­dyś zo­stać prze­nie­sio­ny na ser­wer lub bę­dzie rea­li­zo­wa­ny wie­lo­wąt­ko­wo, uwzględ­nie­nie asyn­chro­niz­mu już w pierw­szym pro­jek­cie mo­że oszczę­dzić du­żo pra­cy w przy­szło­ści.