LEARNING JAVASCRIPT - Trang 227

leaving

i

with the value

–1

, and only then do the callbacks start executing. The prob‐

lem is, when they execute,

i

already has the value

–1

.

The important lesson here is understanding the way scope and asynchronous execu‐

tion relate to each other. When we invoke

countdown

, we’re creating a closure that

contains the variable

i

. All of the (anonymous) callbacks that we create in the

for

loop all have access to

i

—the same

i

.

The tidy thing about this example is that inside the

for

loop, we see

i

used in two

different ways. When we use it to calculate the timeout (

(5-i)*1000

), it works as

expected: the first timeout is

0

, the second timeout is

1000

, the third timeout is

2000

,

and so on. That’s because that calculation is synchronous. As a matter of fact, the call

to

setTimeout

is also synchronous (which requires the calculation to happen so that

setTimeout

knows when to invoke the callback). The asynchronous part is the func‐

tion that’s passed to

setTimeout

, and that’s where the problem occurs.

Recall that we can solve this problem with an immediately invoked function expres‐

sion (IIFE), or more simply by just moving the declaration of

i

into the

for

loop

declaration:

function

countdown

() {

console

.

log

(

"Countdown:"

);

for

(

let

i

=

5

;

i

>=

0

;

i

--

) {

// i is now block-scoped

setTimeout

(

function

() {

console

.

log

(

i

===

0

?

"GO!"

:

i

);

}, (

5

-

i

)

*

1000

);

}
}

countdown

();

The takeaway here is that you have to be mindful of the scope your callbacks are

declared in: they will have access to everything in that scope (closure). And because

of that, the value may be different when the callback actually executes. This principle

applies to all asynchronous techniques, not just callbacks.

Error-First Callbacks

At some point during the ascendancy of Node, a convention called

error-first call‐

backs established itself. Because callbacks make exception handling difficult (which

we’ll see soon), there needed to be a standard way to communicate a failure to the

callback. The convention that emerged was to use the first argument to a callback to

receive an error object. If that error is

null

or

undefined

, there was no error.

Whenever you’re dealing with an error-first callback, the first thing you should do is

check the error argument and take appropriate action. Consider reading the contents

of a file in Node, which adheres to the error-first callback convention:

Callbacks | 203

Liên Kết Chia Sẽ

** Đây là liên kết chia sẻ bới cộng đồng người dùng, chúng tôi không chịu trách nhiệm gì về nội dung của các thông tin này. Nếu có liên kết nào không phù hợp xin hãy báo cho admin.