skip to Main Content

I’m stuck with a work-related task where I’m fetching data from the db and then send the data to an external api through post request. Right now I’m succesfully getting the data and processed it but the external api request gets through before the promise is resolved.

So I have this service class called EmployeeService, where I am getting some data from the db and processing it. To make it more readable I separated each steps in separate methods.

class EmployeeService {
  constructor() {
    this.employeeRepository = new EmployeeRepository();
  }

  getData(employeeId, department {
    return {
      name       : 'John Doe',
      attendance : this.getAttendanceHistory(employeeId, department)
    };
  }

  async getAttendanceHistory(employeeId, department) {
    if (department === 'accounts') {
      return await this.#getAccountsDepartmentHistory(employeeId);
    }
  }

  async #getAccountsDepartmentHistory(employeeId) {
    const 
      cursor = await this.employeeRepository
        .getHistory(
          employeeId
        ),
      
      messages  = await cursor.toArray();
      
    return messages.map((entry) => this.employeeService.processHistory(entry));
  }
}

The above getData method is being called from another service called EmployeeRecordsService and then calls apiService with the data to send to an external endpoint.

class EmployeeRecordsService {
  constructor() {
    this.employeeService = new EmployeeService();
    this.apiService      = new ApiService();
  }

  sendData() {
    const data     = this.employeeService.getData('123', 'accounts');
    const response = this.apiService.send(data);

    return response;
  }
}
class ApiService {
  async send(data) {
    console.log('final data: ', data)

    return await this.request(
      data
    );
  }

}

In EmployeeService, if I log the return value of getAccountsDepartmentHistory, I get all the history and the promise is resolved. Same way, if I log the value of getAttendanceHistory, the promise is resolved. However, if I log the return value of getData it is either pending, or empty array or empty object. And also, final data log gets called with no attendance data with empty object. I tried different ways to resolve the promise in getData method like Promise.resolve, Promise.all and async/await, then final data log shows Promise Pending.

How can I resolve the promise in EmployeeService instead of resolving in other services above? Why does each method in EmployeeService returns a promise even though I’m using await?

Please note that I need to resolve the promise in EmployeeService before getting the data in EmployeeRecordsService. I’m trying to avoid making changes in other parts project cause a lot of things might break.

2

Answers


  1. sendData does nothing to wait on either promise. You need to actually await your calls to getData and send, it’s not enough for those functions to be asynchronous down inside their implementations; callers all the way up the stack must also be asynchronous and must await the promises being returned.

    Login or Signup to reply.
  2. Unfortunately when you have Promise / async actions, all your callers of an async function (In this case getAttendanceHistory is async) needs to handle those Promise. It doesn’t matter whether you await inside those functions already. A suggestion to fix your issue would be make sure to async and await them:

    class EmployeeService {
      constructor() {
        this.employeeRepository = new EmployeeRepository();
      }
    
      async getData(employeeId, department) {
        return {
          name: 'John Doe',
          attendance: await this.getAttendanceHistory(employeeId, department),
        };
      }
    
      async getAttendanceHistory(employeeId, department) {
        if (department === 'accounts') {
          return await this.#getAccountsDepartmentHistory(employeeId);
        }
      }
    
      async #getAccountsDepartmentHistory(employeeId) {
        const cursor = await this.employeeRepository.getHistory(employeeId),
          messages = await cursor.toArray();
    
        return messages.map((entry) => this.employeeService.processHistory(entry));
      }
    }
    
    class EmployeeRecordsService {
      constructor() {
        this.employeeService = new EmployeeService();
        this.apiService = new ApiService();
      }
    
      async sendData() {
        const data = await this.employeeService.getData('123', 'accounts');
        const response = this.apiService.send(data);
    
        return response;
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search