Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Introduction: callbacks#232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
vplentinax merged 12 commits intojavascript-tutorial:masterfromcortizg:es.javascript.info.1-11-01-cb
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
12 commits
Select commitHold shift + click to select a range
1c9ce3d
1-11-01-cb Traducido 16
cortizgJun 6, 2020
f88d911
Merge branch 'master' into es.javascript.info.1-11-01-cb
cortizgJun 7, 2020
dc67c6a
Update 1-js/11-async/01-callbacks/01-animate-circle-callback/task.md
cortizgJun 10, 2020
1a02207
Update 1-js/11-async/01-callbacks/01-animate-circle-callback/task.md
cortizgJun 10, 2020
cde6887
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
7391b93
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
b0c44e0
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
2a5ad0f
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
421601d
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
4a811eb
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
3bc4874
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
8d15a81
Update 1-js/11-async/01-callbacks/article.md
cortizgJun 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,14 +22,14 @@

<body>

<button onclick="go()">Click me</button>
<button onclick="go()">Pruébame</button>

<script>

function go() {
showCircle(150, 150, 100, div => {
div.classList.add('message-ball');
div.append("Hello, world!");
div.append("Hola, mundo!");
});
}

Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@

#Animated circle with callback
#Círculo animado con función de callback

In the task <info:task/animate-circle>an animated growing circle is shown.
En la tarea <info:task/animate-circle>se muestra un círculo creciente animado.

Now let's say we need not just a circle, but to show a message inside it. The message should appear *after* the animation is complete (the circle is fully grown),otherwise it would look ugly.
Ahora digamos que necesitamos no solo un círculo, sino mostrar un mensaje dentro de él. El mensaje debería aparecer *después* de que la animación esté completa (el círculo es desarrollado completamente),de lo contrario se vería feo.

In the solution of the task, the function `showCircle(cx, cy, radius)`draws the circle, but givesnoway to track when it's ready.
En la solución de la tarea, la función `showCircle(cx, cy, radius)`dibuja el círculo, peronohay forma de saber cuando lo termina.

Add a callback argument: `showCircle(cx, cy, radius, callback)`to be called when the animation is complete. The `callback`should receive the circle `<div>`as an argument.
Agrega un argumento callback: `showCircle(cx, cy, radius, callback)`que se llamará cuando se complete la animación. El `callback`debería recibir el círculo `<div>`como argumento.

Here's the example:
Aqui el ejemplo:

```js
showCircle(150, 150, 100, div => {
div.classList.add('message-ball');
div.append("Hello, world!");
div.append("Hola, mundo!");
});
```

Demo:
Demostración:

[iframe src="solution" height=260]

Take the solution of the task <info:task/animate-circle>as the base.
Toma la solución de la tarea <info:task/animate-circle>como base.
176 changes: 100 additions & 76 deletions1-js/11-async/01-callbacks/article.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,66 @@
# Introducción: funciones de retrollamadas (callbacks)

```warn header="Usamos métodos de navegador en estos ejemplos"
Para demostrar el uso de callbacks, promesas y otros conceptos abstractos, utilizaremos algunos métodos de navegador: específicamente, carga de scripts y simples manipulaciones de documentos.

# Introduction: callbacks
Si no estás familiarizado con estos métodos, y los ejemplos son confusos, puedes leer algunos capítulos de esta [sección](/document) del tutorial.

```warn header="We use browser methods in examples here"
To demonstrate the use of callbacks, promises and other abstract concepts, we'll be using some browser methods: specifically, loading scripts and performing simple document manipulations.

If you're not familiar with these methods, and their usage in the examples is confusing, you may want to read a few chapters from the [next part](/document) of the tutorial.

Although, we'll try to make things clear anyway. There won't be anything really complex browser-wise.
Sin embargo, intentaremos aclarar las cosas de todos modos. No habrá nada en cuanto al navegador realmente complejo.
```

Many functions are provided by JavaScripthostenvironments that allow you to schedule *asynchronous* actions. In other words, actions that we initiate now, but they finish later.
Muchas funciones son proporcionadas por el entorno dehostde Javascript que permiten programar acciones *asíncronas*. En otras palabras, acciones que iniciamos ahora, pero que terminan más tarde.

For instance, one such function is the`setTimeout` function.
Por ejemplo, una de esas funciones es la función`setTimeout`.

There are other real-world examples of asynchronous actions, e.g. loadingscriptsand modules (we'll cover them in later chapters).
Hay otros ejemplos del mundo real de acciones asincrónicas, p. ej.: la carga descriptsy módulos (a cubrirse en capítulos posteriores).

Take a look at the function `loadScript(src)`,that loads a scriptwith the given`src`:
Echa un vistazo a la función `loadScript(src)`,que carga un scriptdado:`src`

```js
function loadScript(src) {
//creates a<script>tag and append it to the page
//this causes thescriptwith givensrcto start loading and run when complete
//crea una etiqueta<script>y la agrega a la página
//esto hace que elscriptdado:srccomience a cargarse y ejecutarse cuando se complete
let script = document.createElement('script');
script.src = src;
document.head.append(script);
}
```

It appends to the document the new, dynamically created, tag`<script src="…">`with given `src`. The browser automatically starts loading it and executes when complete.
Anexa al documento la nueva etiqueta, creada dinámicamente,`<script src =" ...">`con el `src` dado. El navegador comienza a cargarlo automáticamente y se ejecuta cuando se completa.

We can use this function like this:
Esta función la podemos usar así:

```js
//load and execute the scriptat the given path
//cargar y ejecutar el scripten la ruta dada
loadScript('/my/script.js');
```

The scriptis executed "asynchronously",as it starts loading now, but runs later, when the function has already finished.
El scriptse ejecuta "asincrónicamente",ya que comienza a cargarse ahora, pero se ejecuta más tarde, cuando la función ya ha finalizado.

If there's any code below`loadScript(…)`,it doesn't wait until the script loading finishes.
El código debajo de`loadScript (...)`,no espera que finalice la carga del script.

```js
loadScript('/my/script.js');
//the code below loadScript
//doesn't wait for the script loading to finish
//el código debajo de loadScript
//no espera a que finalice la carga del script
// ...
```

Let's say we need to use the newscriptas soon as it loads. It declares new functions, and we want to run them.
Digamos que necesitamos usar el nuevoscripttan pronto como se cargue. Declara nuevas funciones, y queremos ejecutarlas.

But if we do that immediately after the `loadScript(…)` call, that wouldn't work:
Si hacemos eso inmediatamente después de llamar a `loadScript (...)`, no funcionará:

```js
loadScript('/my/script.js'); //the scripthas "function newFunction() {…}"
loadScript('/my/script.js'); //el scripttiene a "function newFunction() {…}"

*!*
newFunction(); // nosuch function!
newFunction(); // nohay dicha función!
*/!*
```

Naturally, the browser probably didn't have time to load the script.As of now, the`loadScript`function doesn't provide a way to track the load completion. The scriptloads and eventually runs, that's all. But we'd like to know when it happens, to use new functions and variablesfrom that script.
Naturalmente, el navegador probablemente no tuvo tiempo de cargar el script.Hasta el momento, la función`loadScript`no proporciona una forma de rastrear la finalización de la carga. El scriptse carga y finalmente se ejecuta, eso es todo. Pero nos gustaría saber cuándo sucede, para usar las funciones y variablesnuevas de dicho script.

Let's add a `callback`function as a second argument to`loadScript`that should execute when the script loads:
Agreguemos una función `callback`como segundo argumento para`loadScript`que debería ejecutarse cuando se carga el script:

```js
function loadScript(src, *!*callback*/!*) {
Expand All@@ -77,19 +75,19 @@ function loadScript(src, *!*callback*/!*) {
}
```

Now if we want to call new functions from thescript,we should write that in the callback:
Ahora, si queremos llamar las nuevas funciones desde elscript,deberíamos escribirlo en la callback:

```js
loadScript('/my/script.js', function() {
//the callbackruns after the script is loaded
newFunction(); //so now it works
//la callbackse ejecuta luego que se carga el script
newFunction(); //ahora funciona
...
});
```

That's theidea:the second argument is a function (usually anonymous) that runs when the action is completed.
Esa es laidea:el segundo argumento es una función (generalmente anónima) que se ejecuta cuando se completa la acción.

Here's a runnable example with a realscript:
Aquí un ejemplo ejecutable con unscript real:

```js run
function loadScript(src, callback) {
Expand All@@ -101,39 +99,39 @@ function loadScript(src, callback) {

*!*
loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
alert(`Cool, the script ${script.src}is loaded`);
alert( _ ); //function declared in the loadedscript
alert(`Genial, el script ${script.src}está cargado`);
alert( _ ); //función declarada en elscript cargado
});
*/!*
```

That's called a "callback-based" style of asynchronous programming. A function that does something asynchronously should provide a `callback`argument where we put the function to run after it's complete.
Eso se llama programación asincrónica "basado encallback". Una función que hace algo de forma asincrónica debería aceptar un argumento de `callback`donde ponemos la función por ejecutar después de que se complete.

Here we did it in`loadScript`,but of course it's a general approach.
Aquí lo hicimos en`loadScript`,pero por supuesto es un enfoque general.

## Callbackin callback
## Callbacken una callback

How can we load twoscriptssequentially: the first one, and then the second one after it?
¿Cómo podemos cargar dosscriptssecuencialmente: el primero y después el segundo al cargarse el primero?

Thenaturalsolution would be to put the second`loadScript`call inside the callback,like this:
La soluciónnaturalsería poner la segunda llamada`loadScript`dentro de la callback,así:

```js
loadScript('/my/script.js', function(script) {

alert(`Cool, the ${script.src}is loaded, let's load one more`);
alert(`Genial, el ${script.src}está cargado, carguemos uno más`);

*!*
loadScript('/my/script2.js', function(script) {
alert(`Cool, the second scriptis loaded`);
alert(`Genial, el segundo scriptestá cargado`);
});
*/!*

});
```

After the outer`loadScript`is complete, the callbackinitiates the inner one.
Una vez que se completa el`loadScript`externo, la callbackinicia el interno.

What if we want one morescript...?
¿Qué pasa si queremos unscript más...?

```js
loadScript('/my/script.js', function(script) {
Expand All@@ -142,7 +140,7 @@ loadScript('/my/script.js', function(script) {

*!*
loadScript('/my/script3.js', function(script) {
// ...continue after all scripts are loaded
// ...continua despues que se han cargado todos los scripts
});
*/!*

Expand All@@ -151,13 +149,13 @@ loadScript('/my/script.js', function(script) {
});
```

So, every new action is inside acallback.That's fine for few actions, but not good for many, so we'll see other variants soon.
Entonces, cada nueva acción está dentro de unacallback.Eso está bien para algunas acciones, pero no es bueno para todas, así que pronto veremos otras variantes.

##Handling errors
##Manejo de errores

In the above examples we didn't consider errors. What if the script loading fails? Our callbackshould be able to react on that.
En los ejemplos anteriores no consideramos los errores. ¿Qué pasa si falla la carga del script? Nuestra callbackdebería poder reaccionar ante eso.

Here's an improved version of `loadScript`that tracks loading errors:
Aquí una versión mejorada de `loadScript`que rastrea los errores de carga:

```js
function loadScript(src, callback) {
Expand All@@ -166,39 +164,39 @@ function loadScript(src, callback) {

*!*
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Script load error for ${src}`));
script.onerror = () => callback(new Error(`Error de carga de script con ${src}`));
*/!*

document.head.append(script);
}
```

It calls`callback(null, script)`for successful load and`callback(error)` otherwise.
Para una carga exitosa llama a`callback(null, script)`y de lo contrario a`callback(error)`.

The usage:
El uso:
```js
loadScript('/my/script.js', function(error, script) {
if (error) {
//handle error
//maneja el error
} else {
// scriptloaded successfully
// scriptcargado satisfactoriamente
}
});
```

Once again, the recipe that we used for`loadScript`is actually quite common. It's called the "error-first callback" style.
Una vez más, la receta que usamos para`loadScript`es bastante común. Se llama el estilo de "callbackerror primero".

The convention is:
1.The first argument of the `callback` is reserved for an error if it occurs. Then`callback(err)` is called.
2.The second argument (and the next ones if needed) are for the successful result. Then`callback(null, result1, result2…)` is called.
La convención es:
1.El primer argumento de la 'callback' está reservado para un error, si ocurre. Entonces se llama a`callback(err)`.
2.El segundo argumento (y los siguientes si es necesario) son para el resultado exitoso. Entonces se llama a`callback(null, result1, result2 ...)`.

So the single `callback` function is used both for reporting errors and passing back results.
Por lo tanto, la única función de 'callback' se usa tanto para informar errores como para transferir resultados.

##Pyramid of Doom
##Pirámide de funciones callback

From the first look, it's aviableway of asynchronous coding. And indeed it is. For one or maybe two nested calls it looks fine.
A primvera vista, es una formaviablede codificación asincrónica. Y de hecho lo es. Para una o quizás dos llamadas anidadas, se ve bien.

But for multiple asynchronous actions that follow one after another we'll have code like this:
Pero para múltiples acciones asincrónicas que van una tras otra, tendremos un código como este:

```js
loadScript('1.js', function(error, script) {
Expand All@@ -217,7 +215,7 @@ loadScript('1.js', function(error, script) {
handleError(error);
} else {
*!*
// ...continue after all scripts are loaded (*)
// ...continua después que se han cargado todos los script (*)
*/!*
}
});
Expand All@@ -228,14 +226,39 @@ loadScript('1.js', function(error, script) {
});
```

In the code above:
1. We load `1.js`, then if there's no error.
2. We load `2.js`, then if there's no error.
3. We load `3.js`, then if there's no error -- do something else `(*)`.
En el código de arriba:
1. Cargamos `1.js`, entonces si no hay error.
2. Cargamos `2.js`, entonces si no hay error.
3. Cargamos `3.js`, luego, si no hay ningún error, haga otra cosa `(*)`.


A medida que las llamadas se anidan más, el código se vuelve más profundo y difícil de administrar, especialmente si tenemos un código real en lugar de '...' que puede incluir más bucles, declaraciones condicionales, etc.

As calls become more nested, the code becomes deeper and increasingly more difficult to manage, especially if we have real code instead of `...` that may include more loops, conditional statements and so on.
A esto se le llama "callback hell" o "Pirámide de Doom".

That's sometimes called "callback hell" or "pyramid of doom."
<!--
loadScript('1.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
}
});
}
})
}
});
-->

<!--
loadScript('1.js', function(error, script) {
Expand DownExpand Up@@ -263,11 +286,11 @@ loadScript('1.js', function(error, script) {

![](callback-hell.svg)

The "pyramid" of nested calls grows to the right with every asynchronous action. Soon it spirals out of control.
La "pirámide" de llamadas anidadas crece a la derecha con cada acción asincrónica. Pronto se sale de control.

So this way of coding isn't very good.
Entonces, esta forma de codificación no es tan buena.

We can try to alleviate the problem by making every action a standalone function, like this:
Trataremos de aliviar el problema haciendo cada acción una función independiente, asi:

```js
loadScript('1.js', step1);
Expand All@@ -294,17 +317,18 @@ function step3(error, script) {
if (error) {
handleError(error);
} else {
// ...continue after all scripts are loaded (*)
// ...continua despues que se han cargado todos los scripts (*)
}
};
```

See? It does the same, and there's no deep nesting now because we made every action a separate top-level function.
¿Lo Ves? Hace lo mismo, y ahora no hay anidamiento profundo porque convertimos cada acción en una función de nivel superior separada.

Funciona, pero el código parece una hoja de cálculo desgarrada. Es difícil de leer, y habrías notado que hay que saltar de un lado a otro mientras lees. Es un inconveniente, especialmente si el lector no está familiarizado con el código y no sabe dónde dirigirse.

It works, but the code looks like a torn apart spreadsheet. It's difficult to read, and you probably noticed that one needs to eye-jump between pieces while reading it. That's inconvenient, especially if the reader is not familiar with the code and doesn't know where to eye-jump.

Also, the functions named `step*`are all of single use, they are created only to avoid the "pyramid of doom." No one is going to reuse them outside of the action chain. So there's a bit of namespace cluttering here.
Además, las funciones llamadas `step*`son de un solo uso, son para evitar la "Pirámide de funciones callback". Nadie los reutilizará fuera de la cadena de acción. Así que hay muchos nombres abarrotados aquí.

We'd like to have something better.
Nos gustaría tener algo mejor.

Luckily, there are other ways to avoid such pyramids. One of the best ways is to use "promises," described in the next chapter.
Afortunadamente, podemos evitar tales pirámides. Una de las mejores formas es usando "promesas", descritas en el próximo capítulo.

[8]ページ先頭

©2009-2025 Movatter.jp