JavaScript Avanzado

Adolfo Sanz De Diego

Octubre 2015

1 Acerca de

1.1 Autor

1.2 Licencia

1.3 Ejemplos

2 JavaScript

2.1 Historia

2.2 El lenguaje

3 Orientación a objetos

3.1 ¿Qué es un objeto?

3.2 Propiedades (I)

objeto.nombre === objeto[nombre] // true

3.3 Propiedades (II)

var objeto = {};
objeto.nuevaPropiedad = 1; // añadir
delete objeto.nuevaPropiedad; // eliminar

3.4 Objeto iniciador

var objeto = {
  nombre: "Adolfo",
  twitter: "@asanzdiego"
};

3.5 Función constructora

function Persona(nombre, twitter) {
  this.nombre = nombre;
  this.twitter = twitter;
};
var objeto = new Persona("Adolfo", "@asanzdiego");

3.6 Prototipos (I)

3.7 Prototipos (II)

// Falla en Opera o IE <= 8
Object.getPrototypeOf(objeto);

// No es estandar y falla en IE
objeto.__proto__;

3.8 Eficiencia (I)

3.9 Eficiencia (II)

function ConstructorA(p1) {
  this.p1 = p1;
}

// los métodos los ponenmos en el prototipo
ConstructorA.prototype.metodo1 = function() {
  console.log(this.p1);
};

3.10 Herencia

function ConstructorA(p1) {
  this.p1 = p1;
}

function ConstructorB(p1, p2) {
  // llamamos al super para que no se pierda p1.
  ConstructorA.call(this, p1);
  this.p2 = p2;
}

// Hacemos que B herede de A
// Prototipo de Función Constructora B apunta al
// Prototipo de Función Constructora A
ConstructorB.prototype = Object.create(ConstructorA.prototype);

3.11 Cadena de prototipos

3.12 Cadena de prototipos de la instancia

instanciaB.__proto__ == ConstructorB.prototype // true
instanciaB.__proto__.__proto__ == ConstructorA.prototype // true
instanciaB.__proto__.__proto__.__proto__ == Object.prototype // true
instanciaB.__proto__.__proto__.__proto__.__proto__ == null // true

3.13 Cadena de prototipos de la función constructora

expect(ConstructorB.__proto__).toEqual(Function.prototype);
expect(ConstructorB.__proto__.__proto__).toEqual(Object.prototype);
expect(ConstructorB.__proto__.__proto__.__proto__).toEqual(null);

3.14 Esquema prototipos

Esquema prototipos
Esquema prototipos

3.15 Operador instanceof

instanciaB instanceof ConstructorB; // true
instanciaB instanceof ConstructorA; // true
instanciaB instanceof Object; // true

3.16 Extensión

String.prototype.hola = function() {
  return "Hola "+this;
}

"Adolfo".hola(); // "Hola Adolfo"

3.17 Propiedades y métodos estáticos (I)

3.18 Propiedades y métodos estáticos (II)

function ConstructorA() {

  ConstructorA.propiedadEstatica = "propiedad estática";
}

ConstructorA.metodoEstatico = function() {
  console.log("método estático");
}

3.19 Propiedades y métodos privados (I)

3.20 Propiedades y métodos privados (II)

function ConstructorA(privada, publica) {
  var propiedadPrivada = privada;
  this.propiedadPublica = publica;
  var metodoPrivado = function() {
    console.log("-->propiedadPrivada", propiedadPrivada);
  }
  this.metodoPublico = function() {
    console.log("-->propiedadPublica", this.propiedadPublica);
    metodoPrivado();
  }
}

3.21 Polimorfismo

4 Técnicas avanzadas

4.1 Funciones

4.2 This

var nombre = "Laura";

var alba = {
  nombre: "Alba",
  saludo: function() {
    return "Hola "+this.nombre;
  }
}

alba.saludo(); // Hola Alba

var fn = alba.saludo;

fn(); // Hola Laura

4.3 call y apply

fn.call(thisArg [, arg1 [, arg2 [...]]])
fn.apply(thisArg [, arglist])

4.4 Número variable de argumentos

4.5 Arguments

function echoArgs() {
  console.log(arguments[0]); // Adolfo
  console.log(arguments[1]); // Sanz
}
echoArgs("Adolfo", "Sanz");

4.6 Declaración de funciones

function holaMundo1() {
  console.log("Hola Mundo 1");
}
holaMundo1();

var holaMundo2 = function() {
  console.log("Hola Mundo 2");
}
holaMundo2();

4.7 Transfiriendo funciones a otras funciones

function saluda() {
  console.log("Hola")
}
function ejecuta(func) {
  func()
}
ejecuta(saluda);

4.8 Funciones anónimas (I)

4.9 Funciones anónimas (II)

function(nombre) {
  console.log("Hola "+nombre);
}

4.10 Funciones anónimas (III)

function saludador(nombre) {
  return function() {
    console.log("Hola "+nombre);
  }
}

var saluda = saludador("mundo");
saluda(); // Hola mundo

4.11 Funciones autoejecutables

(function(nombre) {
  console.log("Hola "+nombre);
})("mundo")

4.12 Clousures (I)

function creaSumador(x) {
  return function(y) {
    return x + y;
  };
}

var suma5 = creaSumador(5);
var suma10 = creaSumador(10);

console.log(suma5(2));  // muestra 7
console.log(suma10(2)); // muestra 12

4.13 Clousures (II)

4.14 El patrón Modulo

miModulo = (function() {

  var propiedadPrivada;

  function metodoPrivado() { };

  // API publica
  return {
    metodoPublico1: function () {
    },

    metodoPublico2: function () {
    }
  }
}());

4.15 Eficiencia (I)

4.16 Eficiencia (II)

miModulo = (function(window, undefined) {

  // El código va aquí

})( window );

4.17 El patrón Modulo Revelado (I)

4.18 El patrón Modulo Revelado (II)

miModulo = (function() {

  function metodoA() { };

  function metodoB() { };

  function metodoC() { };

  // API publica
  return {
    metodoPublico1: metodoA,
    metodoPublico2: metodoB
  }
}());

4.19 Espacios de nombres (I)

miBiblioteca = miBiblioteca || {};

miBiblioteca.seccion1 = miBiblioteca.seccion1 || {};

miBiblioteca.seccion1 = {
  priopiedad: p1,
  metodo: function() { },
};

miBiblioteca.seccion2 = miBiblioteca.seccion2 || {};

miBiblioteca.seccion2 = {
  priopiedad: p2,
  metodo: function() { },
};

4.20 Espacios de nombres (II)


miBiblioteca = miBiblioteca || {};

(function(namespace) {

  var propiedadPrivada = p1;

  namespace.propiedadPublica = p2;

  var metodoPrivado = function() { };

  namespace.metodoPublico = function() { };

}(miBiblioteca));

5 Document Object Model

5.1 ¿Qué es DOM?

5.2 Tipos de nodos

5.3 Recorrer el DOM

getElementById(id)
getElementsByName(name)
getElementsByTagName(tagname)
getElementsByClassName(className)
getAttribute(attributeName)
querySelector(selector)
querySelectorAll(selector)

5.4 Manipular el DOM

createElement(tagName)
createTextNode(text)
createAttribute(attributeName)
appendChild(node)
insertBefore(newElement, targetElement)
removeAttribute(attributename)
removeChild(childreference)
replaceChild(newChild, oldChild)

5.5 Propiedades Nodos (I)

attributes[]
className
id
innerHTML
nodeName
nodeValue
style
tabIndex
tagName
title

5.6 Propiedades Nodos (II)

childNodes[]
firstChild
lastChild
previousSibling
nextSibling
ownerDocument
parentNode

6 Librerías y Frameworks

6.1 jQuery

// Vanilla JavaScript
var elem = document.getElementById("miElemento");

//jQuery
var elem = $("#miElemento");  

6.2 jQuery UI & Mobile

6.3 Frameworks CSS

6.4 MVC en el front

6.5 NodeJS

6.6 Automatización de tareas

6.7 Gestión de dependencias

6.8 Aplicaciones de escritorio multiplataforma

6.9 Aplicaciones móviles híbridas

6.10 WebComponents

6.11 Otros

7 Eventos

7.1 El patrón PubSub (I)

var EventBus = {
  topics: {},

  subscribe: function(topic, listener) {
    if (!this.topics[topic]) this.topics[topic] = [];
    this.topics[topic].push(listener);
  },

  publish: function(topic, data) {
    if (!this.topics[topic] || this.topics[topic].length < 1) return;
    this.topics[topic].forEach(function(listener) {
      listener(data || {});
    });
  }
};

7.2 El patrón PubSub (II)

EventBus.subscribe('foo', alert);
EventBus.publish('foo', 'Hello World!');

7.3 El patrón PubSub (III)

var Mailer = function() {
  EventBus.subscribe('order/new', this.sendPurchaseEmail);
};

Mailer.prototype = {
  sendPurchaseEmail: function(userEmail) {
    console.log("Sent email to " + userEmail);
  }
};

7.4 El patrón PubSub (IV)

var Order = function(params) {
  this.params = params;
};

Order.prototype = {
  saveOrder: function() {
    EventBus.publish('order/new', this.params.userEmail);
  }
};

7.5 El patrón PubSub (V)

var mailer = new Mailer();
var order = new Order({userEmail: 'john@gmail.com'});
order.saveOrder();
"Sent email to john@gmail.com"

7.6 Principales eventos (I)

Evento Descripción
onblur Un elemento pierde el foco
onchange Un elemento ha sido modificado
onclick Pulsar y soltar el ratón
ondblclick Pulsar dos veces seguidas con el ratón

7.7 Principales eventos (II)

Evento Descripción
onfocus Un elemento obtiene el foco
onkeydown Pulsar una tecla y no soltarla
onkeypress Pulsar una tecla
onkeyup Soltar una tecla pulsada
onload Página cargada completamente

7.8 Principales eventos (III)

Evento Descripción
onmousedown Pulsar un botón del ratón y no soltarlo
onmousemove Mover el ratón
onmouseout El ratón "sale" del elemento
onmouseover El ratón "entra" en el elemento
onmouseup Soltar el botón del ratón

7.9 Principales eventos (IV)

Evento Descripción
onreset Inicializar el formulario
onresize Modificar el tamaño de la ventana
onselect Seleccionar un texto
onsubmit Enviar el formulario
onunload Se abandona la página

7.10 Suscripción

var windowOnLoad = function(e) {
  console.log('window:load', e);
};

window.addEventListener('load', windowOnLoad);

window.removeEventListener('load', windowOnLoad);

7.11 Eventos personalizados (I)

var event = new Event('build');

elem.addEventListener('build', function (e) { ... }, false);

7.12 Eventos personalizados (II)

var event = new CustomEvent('build', { 'detail': detail });

elem.addEventListener('build', function (e)  {
  log('The time is: ' + e.detail);
}, false);

7.13 Disparar un evento

function simulateClick() {
  var event = new MouseEvent('click');
  var element = document.getElementById('id');
  element.dispatchEvent(event);
}

7.14 Propagación (I)

               1              2
              | |            / \
+-------------| |------------| |-------------+
| DIV1        | |            | |             |
|   +---------| |------------| |---------+   |
|   | DIV2    | |            | |         |   |
|   |   +-----| |------------| |-----+   |   |
|   |   | A   \ /            | |     |   |   |
|   |   +----------------------------+   |   |
|   +------------------------------------+   |
|           FASE DE        FASE DE           |
|           CAPTURA        BURBUJA           |
|          DE EVENTOS     DE EVENTOS         |
+--------------------------------------------+

7.15 Propagación (II)

// en fase de CAPTURA
addEventListener("eventName",callback, true);

// en fase de BURBUJA
addEventListener("eventName",callback, false); // por defecto

7.16 Propagación (III)

// detiene la propagación del evento
event.stopPropagation();

// elimina las acciones por defecto (ejemplo: abrir enlace)
event.preventDefault();

8 WebSockets

8.1 ¿Qué son los WebSockets?

8.2 Socket.IO

9 AJAX

9.1 ¿Qué es AJAX?

9.2 Tecnologías AJAX

9.3 ¿Qué es el XMLHttpRequest?

9.4 Ejemplo

var http_request = new XMLHttpRequest();
var url = "http://example.net/jsondata.php";

// Descarga los datos JSON del servidor.
http_request.onreadystatechange = handle_json;
http_request.open("GET", url, true);
http_request.send(null);

function handle_json() {
  if (http_request.status == 200) {
    var json_data = http_request.responseText;
    var the_object = eval("(" + json_data + ")");
  } else {
    alert("Ocurrio un problema con la URL.");
  }
}

10 JSON

10.1 ¿Qué es JSON?

10.2 Parse

miObjeto = eval('(' + json_datos + ')');

10.3 Ejemplo

{
    curso: "AJAX y jQuery",
    profesor: "Adolfo",
    participantes: [
        { nombre: "Isabel", edad: 35 },
        { nombre: "Alba", edad: 15 },
        { nombre: "Laura", edad: 10 }
    ]
}

10.4 JSONP

10.5 CORS (I)

10.6 CORS (II)

Access-Control-Allow-Origin: http://dominio-permitido.com

11 APIs REST

11.1 ¿Qué es un API REST?

11.2 ¿Por qué REST?

11.3 Ejemplo API

11.4 Errores HTTP

12 Gestión de dependencias

12.1 AMD

12.2 RequireJS (I)

<!DOCTYPE html>
<html>
    <head>
        <title>Page 1</title>
        <script data-main="js/index" src="js/lib/require.js"></script>
    </head>
    <body>
        <h1>Hola Mundo</h1>
    </body>
</html>

12.3 RequireJS (II)

requirejs(['./common'], function (common) {
    requirejs(['app/main']);
});

12.4 RequireJS (III)

define(function (require) {
    var $ = require('jquery');
    var persona = require('./persona');

    $('h1').html("Hola requery.js");

    var p = new persona("Adolfo", 30);
    p.saludar();
});

12.5 RequireJS (IV)

define(function () {

  var Persona = function(nombre, edad) {

      this.nombre = nombre;

      Persona.prototype.saludar = function() {
          alert("Hola, mi nombre es " + this.nombre);
      };
  }

  return Persona;
});

12.6 CommonJS

12.7 Browserify (I)

npm install -g browserify

12.8 Browserify (II)

npm install

12.9 Browserify (III)

{
  "name": "browserify-example",
  "version": "1.0.0",
  "dependencies": {
    "jquery": "^2.1.3"
  }
}

12.10 Browserify (IV)

browserify js/main.js -o js/bundle.js

12.11 Browserify (V)

<!doctype html>
<html>
  <head>
    <title>Browserify Playground</title>
  </head>
  <body>
    <h1>Hola Mundo</h1>
    <script src="js/bundle.js"></script>
  </body>
</html>

12.12 Browserify (VI)

var $ = require('jquery');
var persona = require('./persona');

$('h1').html('Hola Browserify');

var p = new persona("Adolfo", 30);
p.saludar();

12.13 Browserify (VII)

var Persona = function(nombre, edad) {

    this.nombre = nombre;

    Persona.prototype.saludar = function() {
        alert("Hola, mi nombre es " + this.nombre);
    };
}

module.exports = Persona;

12.14 ECMAScript 6

13 ES6

13.1 Como usarlo hoy

13.2 Función Arrow (I)

// ES5
var data = [{...}, {...}, {...}, ...];  
data.forEach(function(elem){  
    console.log(elem)
});

13.3 Función Arrow (I)

//ES6
var data = [{...}, {...}, {...}, ...];  
data.forEach(elem => {  
    console.log(elem);
});

13.4 Función Arrow (III)

// ES5
var miFuncion = function(num1, num2) {  
    return num1 + num2;
}

13.5 Función Arrow (IV)

// ES6
var miFuncion = (num1, num2) => num1 + num2;  

13.6 This (I)

//ES5
var objEJ5 = {
  data : ["Adolfo", "Isabel", "Alba"],
  duplicar : function() {
    var that = this;
    this.data.forEach(function(elem){
        that.data.push(elem);
    });
    return this.data;
  }
}

13.7 This (II)

//ES6
var objEJ6 = {
  data : ["Adolfo", "Isabel", "Alba"],
  duplicar : function() {
    this.data.forEach((elem) => {
        this.data.push(elem);
    });
    return this.data;
  }
}

13.8 Definición de Clases (I)

//ES5
var Shape = function (id, x, y) {
    this.id = id;
    this.move(x, y);
};
Shape.prototype.move = function (x, y) {
    this.x = x;
    this.y = y;
};

13.9 Definición de Clases (II)

//ES6
class Shape {
    constructor (id, x, y) {
        this.id = id
        this.move(x, y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

13.10 Herencia de Clases (I)

//ES5
var Rectangle = function (id, x, y, width, height) {
    Shape.call(this, id, x, y);
    this.width  = width;
    this.height = height;
};
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var Circle = function (id, x, y, radius) {
    Shape.call(this, id, x, y);
    this.radius = radius;
};
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

13.11 Herencia de Clases (II)

//ES6
class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)
        this.width  = width
        this.height = height
    }
}
class Circle extends Shape {
    constructor (id, x, y, radius) {
        super(id, x, y)
        this.radius = radius
    }
}

13.12 let (I)

//ES5
(function() {
    console.log(x); // x no está definida aún.
    if(true) {
        var x = "hola mundo";
    }
    console.log(x);
    // Imprime "hola mundo", porque "var"
    // hace que sea global a la función;
})();

13.13 let (II)

//ES6
(function() {
    if(true) {
        let x = "hola mundo";
    }
    console.log(x);
    //Da error, porque "x" ha sido definida dentro del "if"
})();

13.14 Scopes (I)

//ES5
(function () {
    var foo = function () { return 1; }
    foo() === 1;
    (function () {
        var foo = function () { return 2; }
        foo() === 2;
    })();
    foo() === 1;
})();

13.15 Scopes (II)

//ES6
{
    function foo () { return 1 }
    foo() === 1
    {
        function foo () { return 2 }
        foo() === 2
    }
    foo() === 1
}

13.16 const (I)

//ES6
(function() {
    const PI;
    PI = 3.15;
    // ERROR, porque ha de asignarse un valor en la declaración
})();

13.17 const (II)

//ES6
(function() {
    const PI = 3.15;
    PI = 3.14159;
    // ERROR de nuevo, porque es de sólo-lectura
})();

13.18 Template Strings (I)

//ES6
let nombre1 = "JavaScript";  
let nombre2 = "awesome";  
console.log(`Sólo quiero decir que ${nombre1} is ${nombre2}`);  
// Solo quiero decir que JavaScript is awesome

13.19 Template Strings (II)

//ES5
var saludo = "ola " +  
"que " +
"ase ";

13.20 Template Strings (III)

//ES6
var saludo = `ola  
que  
ase`;

13.21 Destructuring (I)

//ES6
var [a, b] = ["hola", "mundo"];  
console.log(a); // "hola"  
console.log(b); // "mundo"

13.22 Destructuring (II)

//ES6
var obj = { nombre: "Adolfo", apellido: "Sanz" };  
var { nombre, apellido } = obj;  
console.log(nombre); // "Adolfo"  
console.log(apellido); // "Sanz"  

13.23 Destructuring (III)

//ES6
var foo = function() {  
    return ["180", "78"];
};
var [estatura, peso] = foo();  
console.log(estatura); //180
console.log(peso); //78

13.24 Parámetros con nombre (I)

//ES5
function f (arg) {
    var name = arg[0];
    var val  = arg[1];
    console.log(name, val);
};
function g (arg) {
    var n = arg.name;
    var v = arg.val;
    console.log(n, v);
};
function h (arg) {
    var name = arg.name;
    var val  = arg.val;
    console.log(name, val);
};
f([ "bar", 42 ]);
g({ name: "foo", val:  7 });
h({ name: "bar", val: 42 });

13.25 Parámetros con nombre (II)

//ES6
function f ([ name, val ]) {
    console.log(name, val)
}
function g ({ name: n, val: v }) {
    console.log(n, v)
}
function h ({ name, val }) {
    console.log(name, val)
}
f([ "bar", 42 ])
g({ name: "foo", val:  7 })
h({ name: "bar", val: 42 })

13.26 Resto parámetros (I)

//ES5
function f (x, y) {
    var a = Array.prototype.slice.call(arguments, 2);
    return (x + y) * a.length;
};
f(1, 2, "hello", true, 7) === 9;

13.27 Resto parámetros (II)

//ES6
function f (x, y, ...a) {
    return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9

13.28 Valores por defecto (I)

//ES5
function(valor) {  
    valor = valor || "foo";
}

13.29 Valores por defecto (I)

//ES6
function(valor = "foo") {...};  

13.30 Exportar módulos

//ES6

// lib/math.js
export function sum (x, y) { return x + y }
export function div (x, y) { return x / y }
export var pi = 3.141593

13.31 Importar módulos

//ES6

// someApp.js
import * as math from "lib/math"
console.log("2π = " + math.sum(math.pi, math.pi))

// otherApp.js
import { sum, pi } from "lib/math"
console.log("2π = " + sum(pi, pi))

13.32 Generadores

//ES6
function *soyUnGenerador(i) {  
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

var gen = soyUnGenerador(1);  
console.log(gen.next());  
//  Object {value: 2, done: false}
console.log(gen.next());  
//  Object {value: 3, done: false}
console.log(gen.next());  
//  Object {value: 4, done: false}
console.log(gen.next());  
//  Object {value: undefined, done: true}

13.33 Set

//ES6
let s = new Set()
s.add("hello").add("goodbye").add("hello")
s.size === 2
s.has("hello") === true
for (let key of s.values()) { // insertion order
  console.log(key)
}

13.34 Map

//ES6
let m = new Map()
m.set("hello", 42)
m.set(s, 34)
m.get(s) === 34
m.size === 2
for (let [ key, val ] of m.entries()) {
  console.log(key + " = " + val)
}

13.35 Nuevos métodos en String

//ES6
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4)   // true
"hello".includes("ell")       // true
"hello".includes("ell", 1)    // true
"hello".includes("ell", 2)    // false

13.36 Nuevos métodos en Number

//ES6
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false

13.37 Proxies

//ES6
let target = {
    foo: "Welcome, foo"
}
let proxy = new Proxy(target, {
    get (receiver, name) {
        return name in receiver ? receiver[name] : `Hello, ${name}`
    }
})
proxy.foo   === "Welcome, foo"
proxy.world === "Hello, world"

13.38 Internacionalization (I)

//ES6
var i10nUSD = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
var i10nGBP = new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP" })
i10nUSD.format(100200300.40) === "$100,200,300.40"
i10nGBP.format(100200300.40) === "£100,200,300.40"

13.39 Internacionalization (II)

//ES6
var i10nEN = new Intl.DateTimeFormat("en-US")
var i10nDE = new Intl.DateTimeFormat("de-DE")
i10nEN.format(new Date("2015-01-02")) === "1/2/2015"
i10nDE.format(new Date("2015-01-02")) === "2.1.2015"

13.40 Promesas (I)

//ES6
var promise = new Promise(function(resolve, reject) {

  var todoCorrecto = true; // o false dependiendo de como ha ido

  if (todoCorrecto) {
    resolve("Promesa Resuelta!");
  } else {
    reject("Promesa Rechazada!");
  }
});

13.41 Promesas (II)

//ES6

// llamamos el metodo 'then' de la promesa
// con 2 callbacks (resolve y reject)
promise.then(function(result) {
  console.log(result); // "Promesa Resuelta!"
}, function(err) {
  console.log(err); // Error: "Promesa Rechazada!"
});

13.42 Promesas (III)

//ES6

// podemos también llamar al 'then' con el callback 'resolve'
// y luego al 'catch' con el callback 'reject'
promise.then(function(result) {
  console.log(result); // "Promesa Resuelta!"
}).catch(function(err) {
  console.log(err); // Error: "Promesa Rechazada!"
});

13.43 Promesas (IV)

//ES6

Promise.all([promesa1,promesa2]).then(function(results) {
  console.log(results); // cuando todas las promesas terminen
}).catch(function(err) {
  console.log(err); // Error: "Error en alguna promesa!"
});

13.44 Promesas (V)

//ES6

Promise.race([promesa1,promesa2]).then(function(firstResult) {
  console.log(firstResult); // cuando termine la primera
}).catch(function(err) {
  console.log(err); // Error: "Error en alguna promesa!"
});

14 Enlaces

14.1 General (ES)

14.2 General (EN)

14.3 Orientación Objetos (ES) (I)

14.4 Orientación Objetos (ES) (II)

14.5 Orientación Objetos (EN)

14.6 Técnicas avanzadas (ES) (I)

14.7 Técnicas avanzadas (ES) (II)

14.8 DOM (ES)

14.9 DOM (EN)

14.10 Frameworks (ES)

14.11 Frameworks (EN)

14.12 Eventos (ES)

14.13 Eventos (EN)

14.14 WebSockets (ES)

14.15 WebSockets (EN)

14.16 AJAX, JSON, REST (ES)

14.17 ES6 (ES)

14.18 ES6 (EN)

/