Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: JS: Miksi muistia kuluu?

juhauta [15.07.2015 17:57:18]

#

Tein pienen?ison html5-ohjelman joka käyttää jqueryä ja siinä on eri välilehdet.
Aina kun välilehtä klikkaa niin käynnistyy siihen liittyvä funktio jonka sisällä on kaikki siihen liittyvät jutut (iso kasa koodia)

Nyt jos välilehtiä klikkailee eestaas (välilehtien vaihto ei lataa sivua uudestaan palvelimelta)niin muistin käyttö kasvaa ja kasvaa ja kasvaa...

onko javascriptitissä tai jqueryssä jotain keinoa joilla saan varmistettua ettei funktioista tule useita kopioita muistiin, niinkuin nyt näyttää käyvän ?
napeissa joissa on jqueryn .on('click') olen jo käyttänyt ennen sitä aina .off('click') joka poisti multitriggerit kun nappeja painoi...
mutta vikaa vielä on

Merri [15.07.2015 18:44:51]

#

Kuulostaa rakenteelliselta ongelmalta, että töitä tehdään moneen kertaan. Useimmiten koodin erittely loogisiin toisistaan irrallisiin kokonaisuuksiin auttaa jo aika paljon. jQueryn kanssa touhutessa on helppo tehdä koodia, joka on varsin spagettimaista, eli toisistaan loogisesti irralliset asiat onkin sekoitettu tapahtumaan yhdessä pitkässä pötkössä. Tämä kuulostaa hieman siltä, miten kuvailet funktiotasi: "iso kasa koodia".

Yksi suosituimpia tapoja eritellä koodia omiin osasiinsa on MVC (Model - View - Controller). Model kuvaa tiedon rakenteen ja on yleensä varsin yksioikoista koodia. View taas hoitaa näyttämislogiikan ja kutsuu tarvittaessa Controlleria. Controller taas hoitaa tiedon jaottelun Modelin tietomallin pohjalle, keskustelut palvelimen suuntaan sekä tarjoilee tiedot Viewille. Yksinkertaistettuna Model ei tiedä mitään siitä, mitä sen sisältämällä tiedolla tehdään, View ei tiedä miten tietoa muutetaan (se vain näyttää sen ja välittää tiedon käyttäjän toimista) ja Controller taas ei tiedä mitään siitä, miten tieto tulisi renderöidä.

Esimerkin MVC:stä löytää vaikkapa TodoMVC:tä katselemalla. Tässä jQuery-esimerkki. Siitä vaan lähdekoodi auki ja tutkimaan (se app.js). Tuo esimerkki ei tosin toteuta varsinaista MVC:tä, mutta esimerkistä käy kuitenkin ilmi miten selkeästi koodia on jaoteltu moniin pieniin osasiin. Pieniä osasia on helpompi käsitellä kuin valtavia mötiköitä.

Metabolix [15.07.2015 21:19:55]

#

Kuten itse jo totesit, yksi yleinen virhe on se, että koodissa luodaan aina vain uusia funktioita. Ei tämän selvittämiseen tarvita mitään työkalua, vaan yksinkertainen ymmärrys JavaScriptin toiminnasta riittää: funktio luodaan siinä, missä on sana function. Useimmat funktiot kannattaa luoda etukäteen. Jos funktion sisällä on toinen funktio, on syytä miettiä, miksi niin on ja onko ratkaisu varmasti järkevä.

// EI NÄIN:
function f() {
	$(x).click(function() {
		alert("moi");
	});
	$(y).click(function() {
		alert("moi");
	});
}
// VAAN NÄIN:
function klikkaus() {
	alert("moi");
}
function f() {
	$(x).click(klikkaus);
	$(y).click(klikkaus);
}

juhauta [16.07.2015 12:12:38]

#

Kiitos vastauksista. Ajattelin tuon niin että kuluttaisi vähemmän muistia kun funktiot ladataan vain silloin kun näkymä tulee näkyviin.
Johtuen myös välimuistiin tallennetuista tiedoista, osa funktioista pitääkin suorittaa aina kun näkymä =välilehti avataan.
Siksi joka välileden avaus sisältää oman käynnistysfunktionsa.

MUTTA

jos näkymässä on nappi ja siitä osaa .on eventin pois .off-toiminnolla,
niin mitä jos siinä onkin tällainen koodi:

$('.form_tallennus_main-input-save').each(function() {
...

eli jokaiseen inputtiin liitetään anonyymi funktio

tuleeko niitä nyt useita aina kun välilehden avaa vai voiko niitä olla vain yksi / elementti ?

Sami [16.07.2015 22:57:07]

#

JQueryn each ei liitä jokaiseen elementtiin funktiota, vaan kutsuu funktiota kerran jokaista tulosjoukon elementtiä kohden. Jokaisella kutsukerralla itse funktio on sama, mutta argumentit eri (indeksi ja elementti).

Todennäköinen syy tuolle muistin kulumiselle on muistivuoto, eli jonnekin jää lojumaan viitteitä objekteihin/funktioihin, esimerkiksi elementtien tapahtumakäsittelijöihin (unohdat kutsua off-funktiota joillekin asettamillesi käsittelijöille?). Myös DOMiin saattaa jäädä turhia elementtejä roikkumaan, jos jokaisella välilehden vaihtokerralla piilotat vanhan välilehden ja luot uuden elementin uutta välilehteä varten.

Ja yksi mahdollinen syy, ainakin siinä tapauksessa että tarkkailit selainprosessin muistinkäyttöä, on ettei roskienkeruu ole vielä käynyt vapauttamassa muistia vaikka kaikki viitteet objekteihin/funktioihin onkin jo poistunut.

Edes suuren määrän anonyymejä funktioita ei pitäisi aiheuttaa muistivuotoa, sillä roskienkeruun pitäisi osata kerätä nekin pois kun viitteitä funktioon ei enää ole. Toki jos funktiolle on mielekästä antaa nimi tai samaa funktiota halutaan käyttää useassa paikassa tai silmukan sisällä, niin tietysti kannattaa käyttää nimettyä funktiota tai sijoittaa anonyymi funktio muuttujaan.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta