torna alle lezioni

decorator ritardante

importanza: 5

Crea il decorator delay(f, ms) che ritarda ogni chiamata ad f di ms millisecondi.

Ad esempio:

function f(x) {
  alert(x);
}

// crea i wrappers
let f1000 = delay(f, 1000);
let f1500 = delay(f, 1500);

f1000("test"); // visualizza "test" dopo 1000ms
f1500("test"); // visualizza "test" dopo 1500ms

In altre parole, delay(f, ms) ritorna una variante di f ritardata di ms.

Nel codice sopra, f è una funzione con un solo argomento, ma la tua soluzione potrebbe passare molti argomenti ed il contesto this.

Apri una sandbox con i test.

La soluzione:

function delay(f, ms) {

  return function() {
    setTimeout(() => f.apply(this, arguments), ms);
  };

}

let f1000 = delay(alert, 1000);

f1000("test"); // mostra "test" dopo 1000ms

Qui, nota come viene utilizzata un arrow function. come sappiamo le arrow functions non hanno un proprio thisarguments, quindi f.apply(this, arguments) prende this e arguments dal wrapper.

Se passassimo una funzione regolare, setTimeout la chiamerebbe senza argomenti ethis = window (supponendo essere in un browser).

Possiamo anche passare il this corretto usando una variabile intermedia, ma è un po’ più complicato:

function delay(f, ms) {

  return function(...args) {
    let savedThis = this; // memorizzalo in una variabile intermedia
    setTimeout(function() {
      f.apply(savedThis, args); // usalo qui
    }, ms);
  };

}

Apri la soluzione con i test in una sandbox.