0

I have a sequence of async/await functions, but they seem to be executing in an order that suggests that execution is not being blocked by the await statements. I'm using Twilio and Sequelize but I imagine the async problem can be diagnosed without knowledge of either of these two packages. Sorry for posting so much code but I feel like I need to include all of it to explain the issue.

My main code is:

app.post('/sms',async function(req,res){
    try{
        worker=await worker.updateWorker('+18005559999',process.env.TWILIO_OFFLINE_SID);
        responseValue="/sms: worker "+worker.friendlyName+" updated to: "+worker.activityName;
        console.log(responseValue);
        res.status(200).send();

    }
    catch(err){
        console.log("/sms error: "+err);
    }
}

worker.updateWorker() is defined in an ES6 class as follows:

async updateWorker(contact_uri,activitySid){
        console.log("updateWorker: getting workerSid from database");
        workerSid=await database.getWorkerSid(contact_uri);
        console.log("updateWorker: workerSid is "+workerSid);
        worker=await this.updateWorkerFromSid(workerSid,activitySid);
        console.log("updateWorker: worker's friendlyName is "+worker.friendlyName);
        return worker;
    }

database.getWorkerSid() is:

getWorkerSid(contact_uri){
        return new Promise(function(resolve,reject){
            sequelize.query("select * from worker where contact_uri='"+contact_uri+"'",
            { type: sequelize.QueryTypes.SELECT})
            .then(result=>{
                if(result.length==0){
                    resolve(null);
                }
                else{
                    resolve(result[0].sid);
                }
            })
            .catch(err=>reject(err));
        });
    }

this.updateWorkerFromSid() is:

async updateWorkerFromSid(workerSid,activitySid){
        var worker;
        try{
            worker=await this.workspace.workers(workerSid)
                        .update({
                            activitySid:activitySid
                        });
            console.log("updateWorkerFromSid: worker has been updated to activity: "+worker.activityName);
            return worker;
        }
        catch(err){
            console.log("updateWorkerFromSid error: "+err);
        }
        finally{
            return worker;
        }

    }

What I end up getting in the console is:

updateWorker: getting workerSid from database
Executing (default): select * from worker where contact_uri='+18005559999'
/sms error: ReferenceError: workerSid is not defined

So this makes me think that we get as far as the sequelize.query() call in database.getWorkerSid(), but then execution proceeds without waiting for the query promise to resolve, and on the line:

console.log("updateWorker: workerSid is "+workerSid);

the workerSid is undefined so there's a crash and the error propagates back up to the try/catch block in the main code.

Basically, what I'm trying to do is:

  1. Get workerSid from database based on contact_uri
  2. Use workerSid to update worker
  3. Once update is complete, output information about the update to console

How should I have my async/await set up to ensure that the events happen in this order?

sigil
  • 9,370
  • 40
  • 119
  • 199
  • 2
    Did you not forget the `async` keyword in `getWorkerSid`? That's the only thing I can think of. Apart from that your code looks fine and you made sure to promisify everything that needs to be. – Azami Feb 07 '19 at 11:29
  • please console result from getWorkerSid function and update your question. – Nikhil G Feb 07 '19 at 11:37
  • 2
    Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Feb 07 '19 at 11:50
  • 1
    You will want to use `let`/`const`/`var` to declare your variables as local! – Bergi Feb 07 '19 at 11:51

1 Answers1

0

I refactored database.getWorkerSid(), to get rid of the Promise constructor anti-pattern, as follows:

async getWorkerSid(contact_uri){
        var workerRow=await this.getRowFromWorkerTable(contact_uri);
        if (workerRow.length==0){
            return null;
        }
        else{
            return workerRow[0].sid;
        }
    }

getRowFromWorkerTable(contact_uri){
        return sequelize.query("select * from worker where contact_uri='"+contact_uri+"'",
        { type: sequelize.QueryTypes.SELECT});
    }

And I declared all my variables in class methods using var, e.g.

var workerSid=await database.getWorkerSid(contact_uri);

It works now.

sigil
  • 9,370
  • 40
  • 119
  • 199