0

I'm having lots of trouble combining a for loop with promises. In essence, my workflow is:

  1. Take an array of Artist objects in Node.js, and grab their biographies and IDs using Mongoose.
  2. Use their IDs to get all the artwork (more specifically, all the artwork keywords) created by that artist.
  3. Train them in a natural language processor classifier (this part isn't super relevant- just know that I need to have access to biography and keywords within the same outer scope.

However, I can't seem to use the bioText object inside the Mongoose promise, and I can't seem to return the keywords from the Mongoose promise.

            if (!isBlank(bioText) && bioText){
                bioText = artist.BIO;
                artworkIdArray.forEach((id)=> {
                        console.log(bioText) // <- prints correct values
                        var getKey = function(){
                    var words = Artwork.findById(id).then((artwork)=>{
                        console.log(bioText) // <- empty string
                    if(artwork.artworkKeywords.length > 0){
                        keywords = artwork.artistKeywords;
                        return keywords;
                    }
                }
                )
                return words;    
                }
                t=getKey();
                t.then((t)=>{
                    console.log(t); // <--- always undefined
                })
            }, this);
        }

As you can see, I try to console.log() after exiting the promise, but the t object is always undefined.

Additionally,

I know that in my example bioText is available right up until the Mongoose find() promise. But I also don't know how to inject bioText into the promise (because then I could simply just train the classifier inside the then() statement.

So my post is basically two questions:

  1. Can Promises use outside variables inside then()?
  2. How do I return a variable declared inside then() so it is available in the outer scope?
Yu Chen
  • 6,540
  • 6
  • 51
  • 86
  • Why do you want to access variable `t` outside the callback function? You can implement a logic like 'when t is evaluated, console.log(t)` but I do not see the point there. Just put all your subsequent code inside the callback function. – RaphaMex Jul 08 '17 at 22:17
  • @R.Saban I'm fine with doing that but how do I get my bioText variable inside the then() statement? – Yu Chen Jul 08 '17 at 22:18

1 Answers1

1
  1. Can Promises use outside variables inside then()?

Yes, but you have to be careful with what happens to those variables later on. That's why console.log(bioText) may log a value just before DB call, and then log null just after DB response.

I would suggest you try the immediate invokation pattern to ensure the value is the expected one:

(function(x){...; console.log(x);})(bioText)
  1. How do I return a variable declared inside then() so it is available in the outer scope?

You cannot, at least without complicated promise management, which you may not need here. That's why t=getKey(); is always undefined.

I think you want to get all the values before going on with your process. So you should retrieve all from DB in a single query, then call all your code in the callback.

You can have a try with this:

Artwork
    .find({_id: {$in: artworkIdArray}})
    .then( (artworks) => {
        var keywords = [];
        artworks.forEach( (artwork) => {
            if(artwork.artworkKeywords.length > 0)
                keywords.append(artwork.artistKeywords);
        });
        // Now do your job with all the retrieved keywords
    });
RaphaMex
  • 2,781
  • 1
  • 14
  • 30
  • Thanks, but the same question persists- I have a bunch of `bioText` string variables from earlier in the code. How do I use them within the `then` statement? – Yu Chen Jul 08 '17 at 22:40
  • Your bioText variable is the scope of the `then` statement, so I do not understand your problem. What error do you get? – RaphaMex Jul 08 '17 at 22:46
  • It is not. Look again at my code- I added in some comments to tell you where the bioText scopes are. It's defined before the promise chain starts (from another result set I grab). I don't get an error, just I get an empty string value. – Yu Chen Jul 08 '17 at 22:49
  • Thanks a lot for answering #2. +1 for t he example. Could you provide an example of an outer scope being used within the then()? Because as you can see in my code comments, bioText is empty inside the then(). – Yu Chen Jul 08 '17 at 22:55
  • From what I can read in your code, I assume that `bioText` gets nullified later. So when `then()` is executed your `bioText` is empty, while it was not at the moment you called the DB. – RaphaMex Jul 08 '17 at 23:09
  • That isn't correct. `bioText` is not nullified later and when then() it is populated with a value already. Could you provide a snippet code of using any variable from an outside scope inside the `then()`? – Yu Chen Jul 08 '17 at 23:25
  • Well you have good examples here: https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron and https://www.npmjs.com/package/mongodb-then and there: https://www.npmjs.com/package/mongodb-then – RaphaMex Jul 08 '17 at 23:37
  • I'm sorry, but where is a good example in those posts? I've read through each one. The first post advocates using callbacks and promises to deal with issues of asynchronicity. The second / third are npm's documentation, that provides a generic use case for a then() statement. Neither show an outer scope variable being injected into a then() statement. – Yu Chen Jul 08 '17 at 23:56
  • Link1: `outerScopeVar` is in then(). Link2: var `db` is reused in then(). Check your code again. – RaphaMex Jul 09 '17 at 01:38