Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are nested promises normal in node.js?

The problem I have been struggling with for two weeks now while learning node.js is how to do synchronous programming using node. I found that no matter how I try to do things sequentially I always end up with nested promises. I have found that there are modules such as Q to help with promise chaining as far as maintainability.

What I don't understand while doing research is Promise.all(), Promise.resolve() and Promise.reject(). Promise.reject is pretty much self explanatory by the name but when writing an application I am confused on how to include any of these in functions or objects without breaking the behavior of the application.

There is definitely a learning curve to node.js when coming from a programming language such as Java or C#. The question that still resides is if promise chaining is normal (best practice) in node.js.

Example:

driver.get('https://website.com/login').then(function () {     loginPage.login('company.admin', 'password').then(function () {         var employeePage = new EmployeePage(driver.getDriver());          employeePage.clickAddEmployee().then(function() {             setTimeout(function() {                 var addEmployeeForm = new AddEmployeeForm(driver.getDriver());                  addEmployeeForm.insertUserName(employee.username).then(function() {                     addEmployeeForm.insertFirstName(employee.firstName).then(function() {                         addEmployeeForm.insertLastName(employee.lastName).then(function() {                             addEmployeeForm.clickCreateEmployee().then(function() {                                 employeePage.searchEmployee(employee);                             });                         });                     });                 });             }, 750);         });     }); }); 
like image 979
Grim Avatar asked Mar 04 '16 20:03

Grim


People also ask

Can promises be nested?

Nested Promise: Promises give you return statements and error throwing, which you lose with continuation-passing style. A nested promise is when you call child promise inside . then of parent promise and this go-on.

Are promises better than callbacks?

They can handle multiple asynchronous operations easily and provide better error handling than callbacks and events. In other words also, we may say that, promises are the ideal choice for handling multiple callbacks at the same time, thus avoiding the undesired callback hell situation.

Can promises be chained?

Example 2: Chaining the Promise with then() Promise resolved You can call multiple functions this way. In the above program, the then() method is used to chain the functions to the promise. The then() method is called when the promise is resolved successfully. You can chain multiple then() methods with the promise.

Why is async await better than promises?

Promise chains can become difficult to understand sometimes. Using Async/Await makes it easier to read and understand the flow of the program as compared to promise chains.


1 Answers

No, one of the great advantages of Promises is that you you can keep your async code linear rather than nested (callback hell from continuation passing style).

Promises give you return statements and error throwing, which you lose with continuation passing style.

You need to return the promise from your async functions so you can chain on the returned value.

Here's an example:

driver.get('https://website.com/login')   .then(function() {     return loginPage.login('company.admin', 'password')   })   .then(function() {     var employeePage = new EmployeePage(driver.getDriver());     return employeePage.clickAddEmployee();   })   .then(function() {     setTimeout(function() {       var addEmployeeForm = new AddEmployeeForm(driver.getDriver());        addEmployeeForm.insertUserName(employee.username)         .then(function() {           return addEmployeeForm.insertFirstName(employee.firstName)         })         .then(function() {           return addEmployeeForm.insertLastName(employee.lastName)         })         .then(function() {           return addEmployeeForm.clickCreateEmployee()         })         .then(function() {           return employeePage.searchEmployee(employee)         });     }, 750); }); 

Promise.all takes an array of promises and resolves once all promises resolve, if any are rejected, the array is rejected. This allows you to execute async code concurrently rather than serially, and still wait for the result of all concurrent functions. If you're comfortable with a threaded model, think spawning threads and then joining.

Example:

addEmployeeForm.insertUserName(employee.username)     .then(function() {         // these two functions will be invoked immediately and resolve concurrently         return Promise.all([             addEmployeeForm.insertFirstName(employee.firstName),             addEmployeeForm.insertLastName(employee.lastName)         ])     })     // this will be invoked after both insertFirstName and insertLastName have succeeded     .then(function() {         return addEmployeeForm.clickCreateEmployee()     })     .then(function() {         return employeePage.searchEmployee(employee)     })     // if an error arises anywhere in the chain this function will be invoked     .catch(function(err){         console.log(err)     }); 

Promise.resolve() and Promise.reject() are methods used when creating a Promise. They're used to wrap an async function using callbacks so that you can work with Promises instead of callbacks.

Resolve will resolve/fulfill the promise (this means a chained then method will be called with the resulting value).
Reject will reject the promise (this means any chained then method(s) will not be called, but the first chained catch method will be called with the error that arose).

I left your setTimeout in place to preserve your programs behavior, but it's likely unnecessary.

like image 92
Tate Thurston Avatar answered Sep 21 '22 13:09

Tate Thurston