0

The project I am working on basically asks users for words they want defined, and then the program pulls in and returns those definitions using API.

What I am trying to accomplish is a flow like this:

  1. ask user for initial word
  2. take user input, feed it to API
  3. retrieve and print API result

  4. ask user for another word they want defined (or, if user types "exit app," the program will close)

  5. retrieve and print API result
  6. loop through 4 & 5 until user types "exit app"

I am running this in Node and have been unable to replicate the above flow. The API functionality is good, but users are getting asked the second question before the results for the first question have been returned. I want the second question to be asked only after the results for the first question have been retrieved and printed.

I have played around with ordering the code in various ways like putting the function asking the second question in the end of the code block for the function asking the first question, which ends up printing the second question before the results of the first one have been obtained.

My understanding of the issue is that it has to do with Node's asynchronous nature, but I am not quite sure how to achieve the flow I'm seeking. Would it be incorporating promises into the code or using something like the async module? Or is it not possible?

The current code block I have for the dictionary query:

var dict = new Oxford(config);

var dictQuery = function(word) {
    var lookup = dict.definitions(word);
    return lookup.then(function(res) {
        var results = res.results;
        var lexicalEntries = results[0]['lexicalEntries'];
        for(var i=0; i < lexicalEntries.length; i++) {
            var objectContainingEntries = lexicalEntries[i];
            var entries = objectContainingEntries['entries'];
            var objectContainingSenses = entries[0];
            var senses = objectContainingSenses['senses'];
            for(var j=0; j < senses.length; j++) {
                var objectContainingDefs = senses[j];
                var defsList = objectContainingDefs['definitions'];
                for(var k=0; k < defsList.length; k++) {
                    var definition = defsList[k].trim();
                }
                console.log("- " + definition);
            }
        }
    })
};

The dictionary module I'm using seems to suggest var lookup returns a promise.

The current code block I have for the questions:

var askUser = function() {
    rl.setPrompt("Please enter the word you would like to define: ");
    rl.prompt();
    rl.on('line', function(word) {
        dictQuery(word.toLowerCase().trim());

        askAgain();
    })
}

var askAgain = function() {
    rl.setPrompt("Is there another word you would like to define? (enter word, or type 'exit app' to leave) ");
    rl.prompt();
    rl.on('line', function(nextWord) {
        if (nextWord.toLowerCase().trim() === 'exit app') {
            rl.close()
        } else {
            dictQuery(nextWord);
            askAgain();
        }
    })
}

askUser();

Thank you for any insight and help you can provide!

*Note: I believe my question differs from the one marked as a possible duplicate because in my case, the second function does not need data generated by the first function to be fed into it.

DevDW
  • 21
  • 3
  • 2
    My guess is within dictQuery you have a async call and you are not blocking for a response. Have you looked into async/await? – Shanerk Jul 23 '18 at 19:38
  • Thanks for the comment Shane -- I updated my question with more code as context for the dictQuery aspect. I believe var lookup, based on the module doc, returns a promise. I'm reading up on async/await and have tried playing around with a few different configurations but haven't reached the desired flow. – DevDW Jul 23 '18 at 21:00
  • Possible duplicate of [Node wait for async function before continue](https://stackoverflow.com/questions/47158979/node-wait-for-async-function-before-continue) – Heretic Monkey Jul 23 '18 at 21:42
  • The linked answer is correct. One thing not highlighted is where the best place is to define async/await. For exactly the problem you are experiencing, I do not like to define the main as async, but instead have wrapper functions that I await making the mainline essentially single threaded. – Shanerk Jul 24 '18 at 13:48
  • Also note, you need to be on Node 8 or higher to use async/await, or get this: https://www.npmjs.com/package/asyncawait – Shanerk Jul 24 '18 at 13:53
  • Thanks Shane. I've been experimenting implementing async-await into the code for about 6 hours now, in each code block and in both, but haven't be able to achieve the flow I'm trying to get. I'm utterly stuck right now... I think my issue relates to how the API is being retrieved. The documentation has lookup.then(function(res) { // execute code... } as being the promise, with res being the JSON response. I haven't been able to pull the JSON in when trying to convert that to async-await. – DevDW Jul 24 '18 at 21:07

0 Answers0