Claus Sandgren
Claus Sandgren

Reputation: 69

Issue with async promise

i'm trying to get a list of matching entities from a querystring. i'm using s3 to store my objects.

The problem is that the promise that resolves the 'main promise' is ansych only return the array when given a setTimeOut. Else it returns [undefined, undefined...].

my code looks like this:

getEntities: (type, offset, limit, query) => {
    return new Promise((resolve, reject) => {

        seekKeys(type, offset, limit, query)
            .then((response) => {

                let entities = [];


                if (response.hasBeenFiltered) { // This is not used yet. 
                    for (let i = offset; i < response.keys.length && i < offset + limit; i++) {
                        entities.push(matchInstance(instance))
                    }

                    resolve(entities)

                } else { // here is where my issue's at.
                    console.log("Keys found: " + response.keys.length)
                    parseQuery(type, query)
                        .then((conditions) => {

                            let matches = response.keys.map((key) => {
                                readEntity(key).then((instance) => {
                                    logger.debug(instance); // logs instances.
                                    matchInstance(instance, conditions)
                                        .then((isMatch) => {
                                            logger.debug("isMatch", isMatch) // logs true/false ?
                                            if (isMatch) {
                                                entities.push(instance);
                                            }
                                        })
                                        .catch((err) => {
                                            logger.error("Failed to match entity: ", err)
                                        })
                                })
                                    .catch((err) => {
                                        logger.error("Failed to read entity: ", err)
                                    })
                            });
                            /*
                            Promise.resolve(matches)
                                .then(() => {
                                    setTimeout(() => {
                                        logger.debug("Match count:", entities.length);
                                        logger.debug("Matching entities:", entities) // logs result of entities
                                    }, 5000)
                                    //resolve(entities)
                                })
                            */
                            Promise.resolve(matches)
                                .then(() => {
                                    logger.debug("Match count:", entities.length);
                                    logger.debug("Matching entities:", entities) // logs [undefined, undefined ....]
                                    resolve(entities)
                                })

                        })
                        .catch((err) => {
                            console.error("Failed to parse query: ", err)
                        });
            })
    })
}`

The format is a bit broken. I'm quite sure why. Please let me know if you need more info.

Upvotes: 1

Views: 46

Answers (1)

traktor
traktor

Reputation: 19301

let matches = response.keys.map((key) => {
    // the mapping function:
    readEntity(key).then((instance) => {

The mapping function does not appear to return a value. This will create a mapped array with undefined elements.

let matches = response.keys.map((key) => {
    return readEntity(key).then((instance) => {
      // mapping function

may work better by filling matches with promises to read and process entities. Waiting for the promises to be fulfilled can be accomplished with Promise.all, so

 Promise.all(matches).then( ... process the entities array

is more likely to work than

Promise.resolve(matches).then( ... process entities

which won't wait for anything asynchronous unless matches is a pending promise - but if that were so, you would not need to resolve it before calling then.

Note the code indentation is confusing, so check the console for errors to see if matches is in scope when processed - I was unable to see that it was.

Upvotes: 2

Related Questions