Are nested promises normal in node.js?

前端 未结 7 1952
说谎
说谎 2020-12-12 13:12

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 thin

7条回答
  •  暖寄归人
    2020-12-12 13:33

    I just answered a similar question where I explained a technique that uses generators to flatten Promise chains in a nice way. The technique gets its inspiration from coroutines.

    Take this bit of code

    Promise.prototype.bind = Promise.prototype.then;
    
    const coro = g => {
      const next = x => {
        let {done, value} = g.next(x);
        return done ? value : value.bind(next);
      }
      return next();
    };
    

    Using it, you can transform your deeply-nested Promise chain into this

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

    Using named generators, we can make that even more legible

    // don't forget to assign your free variables
    // var driver = ...
    // var loginPage = ...
    // var employeePage = new EmployeePage(driver.getDriver());
    // var addEmployeeForm = new AddEmployeeForm(driver.getDriver());
    // var employee = ...
    
    function* createEmployee () {
      yield addEmployeeForm.insertUserName(employee.username);
      yield addEmployeeForm.insertFirstName(employee.firstName);
      yield addEmployeeForm.insertLastName(employee.lastName);
      yield addEmployeeForm.clickCreateEmployee();
      yield employeePage.searchEmployee(employee);
    }
    
    function* login () {
      yield driver.get('https://website.com/login')
      yield loginPage.login('company.admin', 'password');
      yield employeePage.clickAddEmployee();
      setTimeout(() => coro(createEmployee()), 750);
    }
    
    coro(login());
    

    However, this only scratches the surface of what's possible using coroutines to control the flow of promises. Read the answer I linked above that demonstrates some of the other advantages and capabilities of this technique.

    If you do intend to use coroutines for this purpose, I encourage you to check out the co library.

    Hope this helps.

    PS not sure why you're using setTimeout in this fashion. What is the point of waiting for 750 ms specifically ?

提交回复
热议问题