Search code examples
javascriptnode.jsecmascript-6promisees6-promise

Promisified API calls don't execute


I'm writing a service that makes an API call to get all bookings, then from those bookings gets a list all the coworkerIds who made those bookings. I then take the unique ids and use them to make another set of calls, to get an array of all the coworker records. Once this step is done I'll do the same for line item calls, however for some reason I can't get my list of coworker objects.

Here's my code:

apiService.getBookingsList(`?size=1000&from_Booking_FromTime=${weekAgo.toISOString()}`).then(bookings => {
    const bookingCoworkerIds = bookings.map(booking => booking.CoworkerId);
    const bookingCoworkerIdsUnique = bookingCoworkerIds.filter(recordParser.onlyUnique);

    const getCoworker = function getCoworkerInfo(coworkerId)  {
        return apiService.getSingleCoworker(coworkerId);
    }

    const bookingCoworkerCalls = bookingCoworkerIdsUnique.map(coworkerId => getCoworker(coworkerId));
    const bookingCoworkers = Promise.all(bookingCoworkerCalls);

    bookingCoworkers.then(coworkers => {
       console.log(coworkers.length);
       console.log(coworkers[0]);
    });
});

And here's the code for apiService.getSingleCoworker:

getSingleCoworker(coworkerId) {
    // returns a single coworker object given their ID
    return httpsRequest.createRequest(this.URL.coworkerList + `?Coworker_Id=${coworkerId}`, {}, this.requestHeaders, 'GET')
        .then(result => JSON.parse(result).Records[0]);
}

I can also post my https code but I don't think that's the issue.

I suspect I'm doing something wrong with my promise pattern, as I'm still new to promises and async code in general. Neither of these console logs are reached, and instead the only output is:

(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected end of JSON input

So what am I doing wrong here?


Solution

  • The idea of working with promises is chaining "then" calls (or commands).

    In order to do that, a promise must return another promise or a value.

    Like this:

    apiService.getBookingsList(`?size=1000&from_Booking_FromTime=${weekAgo.toISOString()}`)
        .then(bookings => {
            const bookingCoworkerIds = bookings.map(booking => booking.CoworkerId);
            const bookingCoworkerIdsUnique = bookingCoworkerIds.filter(recordParser.onlyUnique);
    
            const bookingPromises = bookingCoworkerIdsUnique.map(coworkerId => apiService.getSingleCoworker(coworkerId));
            return Promise.all(bookingPromises);
    
        }).then(coworkers => {
           console.log(coworkers.length);
           console.log(coworkers[0]);
        }).catch(err => {
            // do something with error
        });
    

    inside the first "then" callback I return Promise.all which generates a promise.

    The next "then" receives all the resolved values by the "all" promise.

    Bear in mind that promises should always contain a "catch" call at the end in order to capture promise errors.

    EDIT:

    getSingleCoworker(coworkerId) {
        const self = this;
        return new Promise(function(resolve, reject) {
            httpsRequest.createRequest(self.URL.coworkerList + `?Coworker_Id=${coworkerId}`, {}, this.requestHeaders, 'GET')
                .then(result => {
                    const jsonVal = JSON.parse(result).Records[0];
                    resolve(jsonVal);
                }).catch(reject);
        });
    }
    

    Hope this helps