Search code examples
javascriptprotractorsalesforcesoql

javascript return statement returning undefined


I am testing an angular js salesforce application using protractor. I need to query for ids using SOQL and jsforce however when I call the query method from another class the return result is undefined. When I print out the log in the method it does show the id I am looking for just seems to get lost in the return statement.

var jsforce = require('jsforce');

function querySF() {
  var conn = new jsforce.Connection({
    // you can change loginUrl to connect to sandbox or prerelease env.
    loginUrl: 'https://www.salesforce.com'
  });
  conn.login('some username', 'some password', function(err, userInfo) {
    if (err) {
      return console.error(err);
    }
    // Now you can get the access token and instance URL information.
    // Save them to establish connection next time.
    console.log(conn.accessToken);
    console.log(conn.instanceUrl);
    // logged in user property
    console.log("User ID: " + userInfo.id);
    console.log("Org ID: " + userInfo.organizationId);
    // ...
  }).then(function() {
    conn.query("SELECT Id FROM anObject__c Where name = 'the name'", function(err, result) {
      if (err) {
        return console.error(err);
      }
      var records = [];
      console.log("total : " + result.totalSize);
      console.log("fetched : " + result.records.length);
      // is returning the id
      console.log(result.records[0].Id);
      // the class that calls the methods saves it to a variable, the variable is undefined
      return result.records[0].Id;
    });
  });


}
After updating my code to match Thomas' answer the below is the error I am receiving

Failed: Helper.querySF is not a function TypeError: Helper.querySF is not a function at Object.it (C:\LimService\LSApp\tests\specs\bookingEvents\EditBookingEventTest.js:23:12) at C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\jasminewd2\index.js:112:25 at new ManagedPromise (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:1067:7) at ControlFlow.promise (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2396:12) at schedulerExecute (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\jasminewd2\index.js:95:18) at TaskQueue.execute_ (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2970:14) at TaskQueue.executeNext_ (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2953:27) at asyncRun (C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2860:25) at C:\Users\nphillips\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:676:7


Solution

  • As mentioned in the comment, you forgot a few return statements.

    Besides that, don't mix promises and callbacks. Especially don't use both to process the same result.

    var jsforce = require('jsforce');
    
    function querySF() {
        var conn = new jsforce.Connection({
            // you can change loginUrl to connect to sandbox or prerelease env.
            loginUrl: 'https://www.salesforce.com'
        });
    
        return conn.login('some username', 'some password')
            .then(function(userInfo) { 
                // Now you can get the access token and instance URL information.
                // Save them to establish connection next time.
                console.log(conn.accessToken);
                console.log(conn.instanceUrl);
                // logged in user property
                console.log("User ID: " + userInfo.id);
                console.log("Org ID: " + userInfo.organizationId);
                // ...
    
                return conn.query("SELECT Id FROM anObject__c Where name = 'the name'")
            })
            .then(function(result){
                  console.log("total : " + result.totalSize);
                  console.log("fetched : " + result.records.length);
                  // is returning the id
                  console.log(result.records[0].Id);
                  // the class that calls the methods saves it to a variable, the variable is undefined
                  return result.records[0].Id;
            })
            .catch(function(err){
                console.error(err);
            });
    }
    

    This seems to work however it returns a promise.

    That's the point of async code, that the result you want ain't there (yet) when the function returns; so you have to deal with a value that will be available at some point in the future.

    One way to do that is by returning a Promise.

    Maybe you should read this: How do I return the response from an asynchronous call?

    It looks as though there are 3 promises being returned, or 3 values at least, the 3rd value is the value i need.

    No, this is just a Promise chain. Only a single value can be returned, and a Promise also, can only resolve to a single value; although that single value may be an Array.

    You should get used to Promises. They are handier than the callback syntax.

    I'm not sure how to access that value.

    like this:

    querySF().then(function(id){
        console.log("result: ", id);
    });