Skip to content

Commit 0b2d72a

Browse files
authored
Merge pull request #232 from cortizg/es.javascript.info.1-11-01-cb
Introduction: callbacks
2 parents 4b9ccb5 + 8d15a81 commit 0b2d72a

File tree

3 files changed

+111
-87
lines changed

3 files changed

+111
-87
lines changed

1-js/11-async/01-callbacks/01-animate-circle-callback/solution.view/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222

2323
<body>
2424

25-
<button onclick="go()">Click me</button>
25+
<button onclick="go()">Pruébame</button>
2626

2727
<script>
2828

2929
function go() {
3030
showCircle(150, 150, 100, div => {
3131
div.classList.add('message-ball');
32-
div.append("Hello, world!");
32+
div.append("Hola, mundo!");
3333
});
3434
}
3535

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11

2-
# Animated circle with callback
2+
# Círculo animado con función de callback
33

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

6-
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.
6+
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.
77

8-
In the solution of the task, the function `showCircle(cx, cy, radius)` draws the circle, but gives no way to track when it's ready.
8+
En la solución de la tarea, la función `showCircle(cx, cy, radius)` dibuja el círculo, pero no hay forma de saber cuando lo termina.
99

10-
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.
10+
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.
1111

12-
Here's the example:
12+
Aqui el ejemplo:
1313

1414
```js
1515
showCircle(150, 150, 100, div => {
1616
div.classList.add('message-ball');
17-
div.append("Hello, world!");
17+
div.append("Hola, mundo!");
1818
});
1919
```
2020

21-
Demo:
21+
Demostración:
2222

2323
[iframe src="solution" height=260]
2424

25-
Take the solution of the task <info:task/animate-circle> as the base.
25+
Toma la solución de la tarea <info:task/animate-circle> como base.

1-js/11-async/01-callbacks/article.md

Lines changed: 100 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,66 @@
1+
# Introducción: funciones de retrollamadas (callbacks)
12

3+
```warn header="Usamos métodos de navegador en estos ejemplos"
4+
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.
25
3-
# Introduction: callbacks
6+
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.
47
5-
```warn header="We use browser methods in examples here"
6-
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.
7-
8-
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.
9-
10-
Although, we'll try to make things clear anyway. There won't be anything really complex browser-wise.
8+
Sin embargo, intentaremos aclarar las cosas de todos modos. No habrá nada en cuanto al navegador realmente complejo.
119
```
1210

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

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

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

19-
Take a look at the function `loadScript(src)`, that loads a script with the given `src`:
17+
Echa un vistazo a la función `loadScript(src)`, que carga un script dado: `src`
2018

2119
```js
2220
function loadScript(src) {
23-
// creates a <script> tag and append it to the page
24-
// this causes the script with given src to start loading and run when complete
21+
// crea una etiqueta <script> y la agrega a la página
22+
// esto hace que el script dado: src comience a cargarse y ejecutarse cuando se complete
2523
let script = document.createElement('script');
2624
script.src = src;
2725
document.head.append(script);
2826
}
2927
```
3028

31-
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.
29+
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.
3230

33-
We can use this function like this:
31+
Esta función la podemos usar así:
3432

3533
```js
36-
// load and execute the script at the given path
34+
// cargar y ejecutar el script en la ruta dada
3735
loadScript('/my/script.js');
3836
```
3937

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

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

4442
```js
4543
loadScript('/my/script.js');
46-
// the code below loadScript
47-
// doesn't wait for the script loading to finish
44+
// el código debajo de loadScript
45+
// no espera a que finalice la carga del script
4846
// ...
4947
```
5048

51-
Let's say we need to use the new script as soon as it loads. It declares new functions, and we want to run them.
49+
Digamos que necesitamos usar el nuevo script tan pronto como se cargue. Declara nuevas funciones, y queremos ejecutarlas.
5250

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

5553
```js
56-
loadScript('/my/script.js'); // the script has "function newFunction() {…}"
54+
loadScript('/my/script.js'); // el script tiene a "function newFunction() {…}"
5755

5856
*!*
59-
newFunction(); // no such function!
57+
newFunction(); // no hay dicha función!
6058
*/!*
6159
```
6260

63-
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 script loads and eventually runs, that's all. But we'd like to know when it happens, to use new functions and variables from that script.
61+
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 script se carga y finalmente se ejecuta, eso es todo. Pero nos gustaría saber cuándo sucede, para usar las funciones y variables nuevas de dicho script.
6462

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

6765
```js
6866
function loadScript(src, *!*callback*/!*) {
@@ -77,19 +75,19 @@ function loadScript(src, *!*callback*/!*) {
7775
}
7876
```
7977

80-
Now if we want to call new functions from the script, we should write that in the callback:
78+
Ahora, si queremos llamar las nuevas funciones desde el script, deberíamos escribirlo en la callback:
8179

8280
```js
8381
loadScript('/my/script.js', function() {
84-
// the callback runs after the script is loaded
85-
newFunction(); // so now it works
82+
// la callback se ejecuta luego que se carga el script
83+
newFunction(); // ahora funciona
8684
...
8785
});
8886
```
8987

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

92-
Here's a runnable example with a real script:
90+
Aquí un ejemplo ejecutable con un script real:
9391

9492
```js run
9593
function loadScript(src, callback) {
@@ -101,39 +99,39 @@ function loadScript(src, callback) {
10199

102100
*!*
103101
loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
104-
alert(`Cool, the script ${script.src} is loaded`);
105-
alert( _ ); // function declared in the loaded script
102+
alert(`Genial, el script ${script.src} está cargado`);
103+
alert( _ ); // función declarada en el script cargado
106104
});
107105
*/!*
108106
```
109107

110-
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.
108+
Eso se llama programación asincrónica "basado en callback". 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.
111109

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

114-
## Callback in callback
112+
## Callback en una callback
115113

116-
How can we load two scripts sequentially: the first one, and then the second one after it?
114+
¿Cómo podemos cargar dos scripts secuencialmente: el primero y después el segundo al cargarse el primero?
117115

118-
The natural solution would be to put the second `loadScript` call inside the callback, like this:
116+
La solución natural sería poner la segunda llamada `loadScript` dentro de la callback, así:
119117

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

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

125123
*!*
126124
loadScript('/my/script2.js', function(script) {
127-
alert(`Cool, the second script is loaded`);
125+
alert(`Genial, el segundo script está cargado`);
128126
});
129127
*/!*
130128

131129
});
132130
```
133131

134-
After the outer `loadScript` is complete, the callback initiates the inner one.
132+
Una vez que se completa el `loadScript` externo, la callback inicia el interno.
135133

136-
What if we want one more script...?
134+
¿Qué pasa si queremos un script más ...?
137135

138136
```js
139137
loadScript('/my/script.js', function(script) {
@@ -142,7 +140,7 @@ loadScript('/my/script.js', function(script) {
142140

143141
*!*
144142
loadScript('/my/script3.js', function(script) {
145-
// ...continue after all scripts are loaded
143+
// ...continua despues que se han cargado todos los scripts
146144
});
147145
*/!*
148146

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

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

156-
## Handling errors
154+
## Manejo de errores
157155

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

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

162160
```js
163161
function loadScript(src, callback) {
@@ -166,39 +164,39 @@ function loadScript(src, callback) {
166164

167165
*!*
168166
script.onload = () => callback(null, script);
169-
script.onerror = () => callback(new Error(`Script load error for ${src}`));
167+
script.onerror = () => callback(new Error(`Error de carga de script con ${src}`));
170168
*/!*
171169

172170
document.head.append(script);
173171
}
174172
```
175173

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

178-
The usage:
176+
El uso:
179177
```js
180178
loadScript('/my/script.js', function(error, script) {
181179
if (error) {
182-
// handle error
180+
// maneja el error
183181
} else {
184-
// script loaded successfully
182+
// script cargado satisfactoriamente
185183
}
186184
});
187185
```
188186

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

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

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

197-
## Pyramid of Doom
195+
## Pirámide de funciones callback
198196

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

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

203201
```js
204202
loadScript('1.js', function(error, script) {
@@ -217,7 +215,7 @@ loadScript('1.js', function(error, script) {
217215
handleError(error);
218216
} else {
219217
*!*
220-
// ...continue after all scripts are loaded (*)
218+
// ...continua después que se han cargado todos los script (*)
221219
*/!*
222220
}
223221
});
@@ -228,14 +226,39 @@ loadScript('1.js', function(error, script) {
228226
});
229227
```
230228

231-
In the code above:
232-
1. We load `1.js`, then if there's no error.
233-
2. We load `2.js`, then if there's no error.
234-
3. We load `3.js`, then if there's no error -- do something else `(*)`.
229+
En el código de arriba:
230+
1. Cargamos `1.js`, entonces si no hay error.
231+
2. Cargamos `2.js`, entonces si no hay error.
232+
3. Cargamos `3.js`, luego, si no hay ningún error, haga otra cosa `(*)`.
233+
234+
235+
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.
235236

236-
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.
237+
A esto se le llama "callback hell" o "Pirámide de Doom".
237238

238-
That's sometimes called "callback hell" or "pyramid of doom."
239+
<!--
240+
loadScript('1.js', function(error, script) {
241+
if (error) {
242+
handleError(error);
243+
} else {
244+
// ...
245+
loadScript('2.js', function(error, script) {
246+
if (error) {
247+
handleError(error);
248+
} else {
249+
// ...
250+
loadScript('3.js', function(error, script) {
251+
if (error) {
252+
handleError(error);
253+
} else {
254+
// ...
255+
}
256+
});
257+
}
258+
})
259+
}
260+
});
261+
-->
239262

240263
<!--
241264
loadScript('1.js', function(error, script) {
@@ -263,11 +286,11 @@ loadScript('1.js', function(error, script) {
263286

264287
![](callback-hell.svg)
265288

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

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

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

272295
```js
273296
loadScript('1.js', step1);
@@ -294,17 +317,18 @@ function step3(error, script) {
294317
if (error) {
295318
handleError(error);
296319
} else {
297-
// ...continue after all scripts are loaded (*)
320+
// ...continua despues que se han cargado todos los scripts (*)
298321
}
299322
};
300323
```
301324

302-
See? It does the same, and there's no deep nesting now because we made every action a separate top-level function.
325+
¿Lo Ves? Hace lo mismo, y ahora no hay anidamiento profundo porque convertimos cada acción en una función de nivel superior separada.
326+
327+
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.
303328

304-
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.
305329

306-
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.
330+
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í.
307331

308-
We'd like to have something better.
332+
Nos gustaría tener algo mejor.
309333

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

0 commit comments

Comments
 (0)