Webprogramozás
Horváth Győző
Egyetemi docens
1117 Budapest, Pázmány Péter sétány 1/c., 2.408-as szoba
Tel: (1) 372-2500/8469
horvath.gyozo@inf.elte.hu
window
, canvas, HTML5 API-kJSON.stringify()
JSON.parse()
{
"Title": "The Hobbit: An Unexpected Journey",
"Year": "2012",
"Rated": "PG-13",
"Released": "14 Dec 2012",
"Runtime": "169 min",
"Genre": "Adventure, Fantasy",
"Director": "Peter Jackson",
"Writer": "Fran Walsh (screenplay), Philippa Boyens (screenplay), Peter Jackson (screenplay), Guillermo del Toro (screenplay), J.R.R. Tolkien (novel)",
"Actors": "Ian McKellen, Martin Freeman, Richard Armitage, Ken Stott",
"Plot": "A reluctant Hobbit, Bilbo Baggins, sets out to the Lonely Mountain with a spirited group of dwarves to reclaim their mountain home, and the gold within it from the dragon Smaug.",
"Language": "English",
"Country": "USA, New Zealand",
"Awards": "Nominated for 3 Oscars. Another 10 wins & 72 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BMTcwNTE4MTUxMl5BMl5BanBnXkFtZTcwMDIyODM4OA@@._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "7.8/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "64%"
},
{
"Source": "Metacritic",
"Value": "58/100"
}
],
"Metascore": "58",
"imdbRating": "7.8",
"imdbVotes": "725,598",
"imdbID": "tt0903624",
"Type": "movie",
"DVD": "19 Mar 2013",
"BoxOffice": "$303,001,229",
"Production": "Warner Bros.",
"Website": "N/A",
"Response": "True"
}
const obj = {
alma: 'piros',
korte: [1, 2, 3]
}
//Sorosítás
const sz = JSON.stringify(obj);
console.log(sz);
// '{"alma":"piros","korte":[1,2,3]}'
//Visszaalakítás
console.log( JSON.parse(sz) );
// Object { alma: "piros", korte: Array[3] }
|--------A--------|
|--------B--------|
1 thread -> |<---A---->||<----B---------->||<------C----->|
thread A -> |<---A---->|
\
thread B ------------> ->|<----B---------->|
\
thread C ----------------------------------> ->|<------C----->|
console.log('first')
alert('second')
console.log('third')
|--------A--------|
|--------B--------|
thread A -> |<---A---->|
thread B -----> |<----B---------->|
thread C ---------> |<------C--------->|
// Timer
console.log('first')
setTimeout(function () {
console.log('second')
}, 1000)
console.log('third')
// Event handler
console.log('first')
button.addEventListener('click', function () {
console.log('second')
})
console.log('third')
Konkurrencia egy szálon
// Szinkron
function a(b) {
b(); // callback
}
console.log('first')
a(function () {
console.log('second')
});
console.log('third')
// vagy
[1, 3, 5].map(e => e * 2)
// Aszinkron
console.log('first')
setTimeout(function () {
console.log('second')
}, 1000)
console.log('third')
setTimeout(() => {
console.log('first')
setTimeout(() => {
console.log('second')
setTimeout(() => {
console.log('third')
setTimeout(() => {
console.log('fourth')
},1000)
}, 1000)
}, 1000)
}, 1000)
pending
, fulfilled
, rejected
function delay(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`${ms} timeout`)
resolve(ms)
}, ms)
})
}
// USING
delay(1000).then(ms => console.log('Result', ms))
delay(1000)
.then(ms => { return delay(500) })
.then(ms => { return delay(2000) })
.then(ms => { return 800 })
.then(ms => { console.log('finally') })
.catch() {
console.log('There are some errors')
}
Promise-okkal dolgozik
async function lotOfDelays() {
try {
await delay(1000)
await delay(500)
await delay(2000)
await delay(800)
}
catch() {
console.log('There are some errors')
}
}
lotOfDelays();
//főszál
const worker = new Worker('masik.js');
worker.onmessage = function(e) {
console.log(e.data);
};
worker.postMessage('valami');
//masik.js
self.onmessage = function(e) {
self.postMessage("Kapott adat: " + e.data);
};
http://www.omdbapi.com/?t=the+shack&apikey=<key>
const input = document.querySelector('input')
const button = document.querySelector('button')
const img = document.querySelector('img')
button.addEventListener('click', getPoster)
function getPoster() {
const title = input.value
const xhr = new XMLHttpRequest();
xhr.open('GET', `http://www.omdbapi.com/?t=${title}&apikey=<key>`, false);
xhr.send(null);
const response = JSON.parse(xhr.responseText)
img.src = response.Poster;
}
load
, loadend
, abort
, error
, timeout
események
function getPoster() {
const title = input.value
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', responseHandler);
xhr.open('GET', `http://www.omdbapi.com/?t=${title}&apikey=<key>`);
xhr.send(null);
}
function responseHandler() {
const response = JSON.parse(this.responseText)
img.src = response.Poster;
}
responseType
, response
function getPoster() {
const title = input.value
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', responseHandler)
xhr.open('GET', `http://www.omdbapi.com/?t=${title}&apikey=<key>`)
xhr.responseType = 'json'
xhr.send(null)
}
function responseHandler() {
img.src = this.response.Poster
}
function getPoster() {
const title = input.value
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', responseHandler)
xhr.addEventListener('error', errorHandler)
xhr.open('GET', `http://www.omdbapi.com/?t=${title}&apikey=<key>`)
xhr.responseType = 'json'
xhr.send(null)
}
function errorHandler() {
console.error('Error')
}
function responseHandler() {
img.src = this.response.Poster
}
progress
esemény
const progress = document.querySelector('progress')
function getPoster() {
const title = document.querySelector('input').value
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', responseHandler)
xhr.addEventListener('progress', progressHandler)
xhr.open('GET', `http://www.omdbapi.com/?t=${title}&apikey=2dd0dbee`)
xhr.responseType = 'json'
xhr.send(null)
}
function progressHandler(e) {
if(e.lengthComputable) {
progress.max = e.total
progress.value = e.loaded
}
}
function responseHandler(e) {
document.querySelector('img').src = this.response.Poster
progress.value = e.loaded
}
Promise-ok
function getPoster() {
const title = document.querySelector('input').value
fetch(`http://www.omdbapi.com/?t=${title}&apikey=2dd0dbee`)
.then(response => response.json())
.then(response => {
document.querySelector('img').src = response.Poster
})
}
// or
async function getPoster() {
const title = document.querySelector('input').value
const response = await fetch(`http://www.omdbapi.com/?t=${title}&apikey=2dd0dbee`)
const json = await response.json()
document.querySelector('img').src = json.Poster
}
this
-lexiaAzaz a this
kontextusa
this
kontextusa//Global
let name = 'Peter'; // window.name
function hello() {
return this.name // this === global (window)
}
hello() // window.hello()
//Method call
let peter = {
name: 'Peter',
describe: function () {
return this.name // this === peter
}
}
peter.describe()
//Constructor call
let Person = function(name) {
this.name = name; // this === instance object
}
let peter = new Person('Peter')
//Setting the context of this with call and apply
let peter = {
name: 'Peter',
hello: function () {
return this.name
}
};
let julia = {
name: 'Julia',
hello: function () {
return this.name
}
};
peter.hello.call(julia) // "Julia"
let peter = {
name: 'Peter',
age: 42,
describe: function () {
function getAge() {
return this.age // this === global (window)
}
return this.name + ':' + getAge() // global call, ~ window.getAge()
}
}
peter.describe() // "Peter:undefined"
//With call and apply
let peter = {
name: 'Peter',
age: 42,
describe: function () {
function getAge() {
return this.age // this depends on the call
}
return this.name + ':' + getAge.call(this)
}
}
peter.describe() // "Peter:42"
//ES5 bind()
let peter = {
name: 'Peter',
age: 42,
describe: function () {
let getAge = (function () {
return this.age // inner this is always outer this
}).bind(this)
return this.name + ':' + getAge()
}
}
peter.describe() // "Peter:42"
//ES6 fat arrow syntax
let peter = {
name: 'Peter',
age: 42,
describe: function () {
let getAge = () => this.age
return this.name + ':' + getAge()
}
}
peter.describe() // "Peter:42"
document.querySelector
const $ = document.querySelector
$('p') // Illegal invocation
// Magyarázat
const document = {
somethingInside: ...,
querySelector: function (sel) {
this.somethingInside
}
}
document.querySelector() // --> this === document
window.$() // --> this === window, window.somethingInside nincs
// Megoldás: a kontextus rögzítése
const $ = document.querySelector.bind(this)
const $ = sel => document.querySelector(sel)
// Alapeset
class AppView {
constructor(appState) {
this.elem = document.querySelector('something')
this.elem.addEventListener('click', this.onClick)
}
onClick(e) {
// this === document.querySelector('something')
}
}
// Bind
class AppView {
constructor(appState) {
this.elem = document.querySelector('something')
this.elem.addEventListener('click', this.onClick.bind(this))
}
onClick(e) {
// this === appView
}
}
// Fat arrow
class AppView {
constructor(appState) {
this.elem = document.querySelector('something')
this.elem.addEventListener('click', e => this.onClick(e))
}
onClick(e) {
// this === appView
}
}
// Class property initializer
class AppView {
constructor(appState) {
this.elem = document.querySelector('something')
this.elem.addEventListener('click', this.onClick)
}
onClick = (e) => {
// this === appView
}
}
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
name
message
try
: védendő kódcatch
: hibakezelő kódfinally
: a végén lefutó kód (nem kötelező)try {
alma.kukacos = true;
}
catch (e) {
console.log(e.name); //ReferenceError
console.log(e.message); //alma is not defined
}
finally { //Elhagyható
console.log('Végem van...');
}
Beépített hiba dobása
if (typeof a !== 'number') {
throw new Error('Nem szam a parameter!');
}
Saját hibaobjektum dobása
if (oszto == 0) {
throw {
name: 'DivisionByZeroError',
message: 'Az oszto nulla!'
};
}
vagy
function DivisionByZeroError(message) {
this.name = "DivisionByZeroError";
this.message = message;
}
//...
if (oszto == 0) {
throw new DivisionByZeroError('Az oszto nulla!');
}
<p>Before</p>
<p id="par">Paragraph to fade out/in</p>
<p>After</p>
const p = document.querySelector('#par');
p.style.transition = 'opacity 1s';
function fadeOut() {
p.style.opacity = 0;
p.addEventListener('transitionend', vege, {once: true});
}
function fadeIn() {
p.removeEventListener('transitionend', vege)
p.style.display = '';
requestAnimationFrame(function () { // waiting for style recalculation
requestAnimationFrame(function () { // before repaint --> next tick
p.style.opacity = 1;
})
});
}
function vege() {
p.style.display = 'none';
}
Ciklustól az időzítőig
function vegrehajtas() {
for (let i = 0; i < 5; i++) {
console.log("feldolgoz", i)
}
}
// A számlálós ciklust átírhatjuk elöltesztelősre
function vegrehajtas(i = 0) {
while (i < 5) {
console.log("feldolgoz", i)
i = i + 1
}
}
// Ebből már könnyű az ismétlődést rekurzióval megoldani,
// tulajdonképpen a `while` helyett `if`-et kell írni,
// és a végén egy rekurzív hívást elhelyezni:
function vegrehajtas(i = 0) {
if (i < 5) {
console.log("feldolgoz", i)
vegrehajtas(i + 1)
}
}
// Az időzítés hasonló a rekurzióhoz, csak nem szinkron közvetlen hívás van, hanem egy aszinkron közvetett.
// Egy állapotváltozóba ki kell szervezni, hogy kell-e újra időzítőt hívni. A mi esetünkben ez az `i` változó volt.
function vegrehajtas(i = 0) {
if (i < 5) {
console.log("feldolgoz", i)
setTimeout(() => vegrehajtas(i + 1), 500)
}
}
// Korábban bevezetett delay függvénnyel
async function vegrehajtas() {
for (let i = 0; i < 5; i++) {
console.log("feldolgoz", i)
await delay(500)
}
}
// Normal, intensive, operation
const table = document.getElementsByTagName("tbody");
for (let i = 0; i < 2000; i++ ) {
const tr = document.createElement("tr");
for (let t = 0; i < 6; i++ )
const td = document.createElement("td");
td.appendChild( document.createTextNode("" + t);
tr.appendChild( td );
}
table.appendChild( tr );
}
// Using a timer to break up a long-running task
const table = document.getElementsByTagName("tbody");
let i = 0;
const max = 1999;
setTimeout(function(){
for (let step = i + 500; i < step; i++ ) {
const tr = document.createElement("tr");
for (let t = 0; i < 6; i++ )
const td = document.createElement("td");
td.appendChild( document.createTextNode("" + t);
tr.appendChild( td );
}
table.appendChild( tr );
}
if ( i < max ) {
setTimeout( arguments.callee, 0 );
}
}, 0);