Async Programming

Why async?

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

Why async?

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

This operation does not depend on the loaded file. Why, then, are we waiting for it to be loaded first?

Why async?

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

This line is blocking the rest of the code

Why async?

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Why async?

This read operation no longer blocks the execution. "hello" will be logged before the file content, even though it appears later in the code

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Event Loop

Event Loop

JavaScript is a single-threaded programming language, meaning it has only a single thread

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

require('fs')

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

readFileSync(...)

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

readFileSync(...)

... taking to long...

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

console.log(...)

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

Event Loop

Call stack

 const fs = require('fs');
 
 const file_data = fs.readFileSync('file.txt', 'utf8');
 
 console.log("Data inside the file:: " + file_data);
 
 console.log("Hi there!");

main()

The call stack stores the function calls. If we invoke a function, we insert it into the call stack, when this function returns, we pop the function out of the stack

console.log(...)

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

Task queue

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

require('fs')

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

readFile(... callback())

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback function

readFile(... callback())

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

callback function

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

console.log()

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

Done?

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

Event loop

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

console.log()

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

callback()

Event Loop

Call stack

main()

The task queue stores tasks to be executed later. The event loop will be watching it.

 const fs = require('fs');
  
 fs.readFile('file.txt', 'utf-8', function (err, data) {
     if (err) throw err;
     console.log("Data inside the file:: " + data)
 
 });
 
 console.log("hello")

Task queue

 (function() {
 
   console.log('1');
 
   setTimeout(function cb() {
     console.log('2');
   }, 10);
 
   console.log('3');
 
   setTimeout(function cb1() {
     console.log('4');
   }, 20);
 
   console.log('5');
 
 })();

What is going to be the logging order?

Activity #1 - callbacks: call me maybe?

Activity #1 - callbacks: call me maybe?

 (function() {
 
   console.log('1');
 
   setTimeout(function cb() {
     console.log('2');
   }, 10);
 
   console.log('3');
 
   setTimeout(function cb1() {
     console.log('4');
   }, 20);
 
   console.log('5');
 
 })();

What is going to be the logging order?

1, 3, 5, 2, 4

Activity #2 - Chaining callbacks: highway to hell

(function() {
 
 console.log("Calling the async functionality");
 
 setTimeout(function initialCB() {
     console.log('Beginning');
 
     setTimeout(function cb() {
         console.log('Reading the folder');
 
         setTimeout(function cb1() {     
             console.log('Going through the files');
         });
      });
 });
 
 console.log("After async");
 
 })();

Activity #2 - Chaining callbacks: highway to hell

(function() {
 
 console.log("Calling the async functionality");
 
 setTimeout(function initialCB() {
     console.log('Beginning');
 
     setTimeout(function cb() {
         console.log('Reading the folder');
 
         setTimeout(function cb1() {     
             console.log('Going through the files');
         });
      });
 });
 
 console.log("After async");
 
 })();

Async block

Activity #2 - Chaining callbacks: highway to hell

What if we want to perform some more async methods on these files?

Activity #2 - Chaining callbacks: highway to hell

(function() {
 
 console.log("Calling the async functionality");
 
 setTimeout(function initialCB() {
     console.log('Beginning');
 
     setTimeout(function cb() {
         console.log('Reading the folder');
 
         setTimeout(function cb1() {     
             console.log('Going through the files');

             setTimeout(function cb2() {
                 console.log("Transform this data");
             });
         });
      });
 });
 
 console.log("After async");
 
 })();

Activity #2 - Chaining callbacks: highway to hell

What if we want to perform even more async methods?

Activity #2 - Chaining callbacks: highway to hell

What if we want to perform even more async methods?

Activity #2 - Chaining callbacks: highway to hell

 (function() {
 
 console.log("Calling the async functionality");
 
 setTimeout(function initialCB() {
     console.log('Beginning');
 
     setTimeout(function cb() {
         console.log('Reading the folder');
 
         setTimeout(function cb1() {     
             console.log('Going through the files');
             setTimeout(function cb2() {
                 console.log("Transform this data");
 
                 setTimeout(function cb3() {
                     console.log("Transform this data");
                     
                     setTimeout(function cb4() {
                         console.log("Transform this data");
                         
                         setTimeout(function cb5() {
                             console.log("Transform this data");
                         });
                     });
                 });
             });
         });
      });
 });
 
 console.log("After async");
 
 })();

Activity #2 - Chaining callbacks: highway to hell

(function() {

console.log("Calling the async functionality");

setTimeout(function initialCB() {
    console.log('Beginning');

    setTimeout(function cb() {
        console.log('Reading the folder');

        setTimeout(function cb1() {
            console.log('Going through the files');
            setTimeout(function cb2() {
                console.log("Transform this data");

                setTimeout(function cb3() {
                    console.log("Transform this data");

                    setTimeout(function cb4() {
                        console.log("Transform this data");

                        setTimeout(function cb5() {
                            console.log("Transform this data");

                            setTimeout(function cb6() {
                                    console.log('Reading the folder');

                                    setTimeout(function cb7() {
                                        console.log('Going through the files');
                                        setTimeout(function cb8() {
                                            console.log("Transform this data");

                                            setTimeout(function cb9() {
                                                console.log("Transform this data");

                                                setTimeout(function cb10() {
                                                    console.log("Transform this data");

                                                    setTimeout(function cb11() {
                                                        console.log("Transform this data");

                                                        setTimeout(function cb12() {
                                                            console.log("Transform this data");

                                                            setTimeout(function cb13() {
                                                                    console.log('Reading the folder');

                                                                    setTimeout(function cb14() {
                                                                        console.log('Going through the files');
                                                                        setTimeout(function cb15() {
                                                                            console.log("Transform this data");

                                                                            setTimeout(function cb16() {
                                                                                console.log("Transform this data");

                                                                                setTimeout(function cb17() {
                                                                                    console.log("Transform this data");

                                                                                    setTimeout(function cb18() {
                                                                                        console.log("Transform this data");
                                                                                    });
                                                                                });
                                                                            });
                                                                        });
                                                                    });
                                                                 });
                                                            });
                                                    });
                                                });
                                            });
                                        });
                                    });
                                 });
                            });
                    });
                });
            });
        });
     });
});

console.log("After async");

})();

Activity #2 - Chaining callbacks: highway to hell

(function() {

console.log("Calling the async functionality");

setTimeout(function initialCB() {
    console.log('Beginning');

    setTimeout(function cb() {
        console.log('Reading the folder');

        setTimeout(function cb1() {
            console.log('Going through the files');
            setTimeout(function cb2() {
                console.log("Transform this data");

                setTimeout(function cb3() {
                    console.log("Transform this data");

                    setTimeout(function cb4() {
                        console.log("Transform this data");

                        setTimeout(function cb5() {
                            console.log("Transform this data");

                            setTimeout(function cb6() {
                                    console.log('Reading the folder');

                                    setTimeout(function cb7() {
                                        console.log('Going through the files');
                                        setTimeout(function cb8() {
                                            console.log("Transform this data");

                                            setTimeout(function cb9() {
                                                console.log("Transform this data");

                                                setTimeout(function cb10() {
                                                    console.log("Transform this data");

                                                    setTimeout(function cb11() {
                                                        console.log("Transform this data");

                                                        setTimeout(function cb12() {
                                                            console.log("Transform this data");

                                                            setTimeout(function cb13() {
                                                                    console.log('Reading the folder');

                                                                    setTimeout(function cb14() {
                                                                        console.log('Going through the files');
                                                                        setTimeout(function cb15() {
                                                                            console.log("Transform this data");

                                                                            setTimeout(function cb16() {
                                                                                console.log("Transform this data");

                                                                                setTimeout(function cb17() {
                                                                                    console.log("Transform this data");

                                                                                    setTimeout(function cb18() {
                                                                                        console.log("Transform this data");
                                                                                    });
                                                                                });
                                                                            });
                                                                        });
                                                                    });
                                                                 });
                                                            });
                                                    });
                                                });
                                            });
                                        });
                                    });
                                 });
                            });
                    });
                });
            });
        });
     });
});

console.log("After async");

})();

Problems with callback style

1. Complex error handling

Problems with callback style

1. Complex error handling

2. Callback hell

Promises in-depth

Promises work like callback functions, in fact, promises are built on top of callback functions. Promises make it way easier to deal with async code. You have to keep in mind two main differences when dealing with promises: using promises and defining promises

Defining promises

function createAsyncFunction () {
  return new Promise(function (resolve, reject) {
    // Do something
    if (allGood) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

Promises in-depth

Promises work like callback functions, in fact, promises are built on top of callback functions. Promises make it way easier to deal with async code. You have to keep in mind two main differences when dealing with promises: using promises and defining promises

p.then((result) => {
  // do something with the result
})
.catch((err) => {
  // do something with error
})

Using promises

Promises in-depth

Promises work like callback functions, in fact, promises are built on top of callback functions. Promises make it way easier to deal with async code. You have to keep in mind two main differences when dealing with promises: using promises and defining promises

try {
    let v = await p();
} catch(e) {
    Log.fatal(e)
}

Using promises

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

Defining an async method using promise

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

Using the previously defined async method

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

This function can only be used asynchronously

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

A promise returns 2 callbacks that you must use to settle the promise

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

resolve the promise if all good

reject otherwise

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

Call the method (which is async)

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

Continue with the normal execution (remember the call stack)

Promises in-depth

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

generateRandomNumber().then(function(result) {
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

When the function returns, we enter the `then()` or `catch()`

Promises in-depth

Chaining promises

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

Chaining async callbacks

Chaining promises

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

Chaining promises

Chaining promises

try {
    let result = await doSomething()
    let nextResult = await doSomethingElse(result)
    let finalResult = await doThirdThing(nextResult)
    console.log('Got the final result: ' + finalResult);
} catch {
 //failureCallback
}

Chaining promises with async/await

Many promises and promises.all()

There are cases where you want to perform the same async action multiple times and wait for all of them to finish in order to continue with the workflow.

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Define async function

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Run many promises

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Run this only when ALL promises are fulfilled

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

All promises fulfilled, run this.

Many promises and promises.all()

 function getRandomInt(max) {
   return Math.floor(Math.random() * Math.floor(max));
 }
 
 var asyncMethod = function() {
    var promise = new Promise(function(resolve, reject){
       setTimeout(function() {
          console.log('Async method completed');
          resolve({status: 200});
       }, getRandomInt(5)*1000 );
    });
    return promise;
 };
 
 console.log("Starting to create many promises")
 
 var p1 = asyncMethod()
 var p2 = asyncMethod()
 var p3 = asyncMethod()
 var p4 = asyncMethod()
 var p5 = asyncMethod()
 
 Promise.all([p1, p2, p3, p4, p5]).then(values => {
   console.log("done: " + JSON.stringify(values))
 });
 
 console.log("I'm going to run before all these guys!");

Hint: you will want to use this when parsing a single course file. A single course file == a promise. Many of these promises == your dataset.

.all() them all

Testing async methods

it('should do something with promises', function() {
  var blah = 'foo';

  var result = asyncMethod();

  return result.then(function(data) {
    expect(data).to.equal(blah);
  })
  .catch(function(err) {
    Log.test("Something went wrong. Message: " + err);
    expect.fail();
  })
});

Using .then() and .catch()

Testing async methods

it('should do something with promises', function() {
  var blah = 'foo';

  var result = asyncMethod();

  return result.then(function(data) {
    expect(data).to.equal(blah);
  })
  .catch(function(err) {
    Log.test("Something went wrong. Message: " + err);
    expect.fail();
  })
});

Using .then() and .catch()

Blocks the test flow and waits for the return

Testing async methods

it('should do something with promises', function() {
  var blah = 'foo';

  var result = asyncMethod();

  return result.then(function(data) {
    expect(data).to.equal(blah);
  })
  .catch(function(err) {
    Log.test("Something went wrong. Message: " + err);
    expect.fail();
  })
});

Using .then() and .catch()

Testing async methods

it("Should add a valid dataset", async () => {
        const id: string = "courses";
        const expectedCode: number = 204;
        let response: InsightResponse;

        try {
            response = await insightFacade.addDataset(id,
                                                      datasets[id],
                                                      InsightDatasetKind.Courses);
        } catch (err) {
            response = err;
        } finally {
            expect(response.code).to.equal(expectedCode);
        }
});

Using async/await

Common mistake

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

var number;

generateRandomNumber().then(function(result) {
  number = result;
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

console.log(number);

Common mistake

function generateRandomNumber () {
  return new Promise(function (resolve, reject) {
    var randomNumber = Math.floor((Math.random() * 10) + 1)
    if (randomNumber <= 5) {
      resolve(randomNumber)
    } else {
      reject(randomNumber)
    }
  })
}

var number;

generateRandomNumber().then(function(result) {
  number = result;
  console.log('Success: ' + result)
}).catch(function(error) {
  console.log('Error: ' + error)
})

console.log(number);

What's going to be logged?

Resources

deck

By Rodrigo Araújo

deck

  • 2,063