How can i return status inside the promise?
Asked Answered
D

1

-3

I started to learning promise with loopback and jsforce, and couldn't handle this problem; I couldn't return status var inside promise to cb() function. Basically i want to connect salesforce and get data via JSforce and write it to db via loopback. Then want to return created/updated/error records to client after remote mothed called.

I'm developing with Loopback via using Node.JS & Express.js I'm using JSforce library to connect salesforce

How can I fix that?

Here is my code:

module.exports = function(Contact) {
  var jsforce = require('jsforce');
  var async = require("async");
  var lr = require('lr.js');

  Contact.ImportContacts = function(cb) {
    // Salesforce Projects List
    var sf_projects = [];
    //Salesforce Conn String
    var conn = lr.SalesforceConn();
    conn.apex.get("/Contact/", function(err, res) {
      var status = {
        "Created": [],
        "Updated": [],
        "Error": ""
      };
      if (err) console.log(err);

      sf_projects = res;
      // Clear result
      status.Created.length = 0;
      status.Updated.length = 0;
      status.Error = "";

      if (sf_projects != undefined) {
        async.eachSeries(sf_projects, function(contact, callback) {
          Contact.findOrCreate({
              where: {
                co_SalesforceID: contact.Id
              }
            }, {
              co_Name: contact.FirstName,
              co_Surname: contact.LastName,
              co_Salutation: contact.Salutation,
              co_Title: contact.Title,
              co_Department: contact.Department,
              co_Email: contact.Email,
              co_PhonePersonal: contact.HomePhone,
              co_PhoneWork: contact.Phone,
              co_PhoneCell: contact.MobilePhone,
              co_Description: contact.Description,
              co_SalesforceID: contact.Id
            },
            function(err, cntct, created) {
              if (err) console.log(err);
              if (created) {
                status.Created.push(cntct.id);
                console.log("Contact created. SalesForeID: " +
                  cntct.co_SalesforceID +
                  " ContactName: " +
                  lr.isDefined(cntct.co_Salutation) + " " +
                  lr.isDefined(cntct.co_Name) + " " +
                  lr.isDefined(cntct.co_Surname));
              } else {
                Contact.replaceById(cntct.id, {
                    co_Name: contact.FirstName,
                    co_Surname: contact.LastName,
                    co_Salutation: contact.Salutation,
                    co_Title: contact.Title,
                    co_Department: contact.Department,
                    co_Email: contact.Email,
                    co_PhonePersonal: contact.HomePhone,
                    co_PhoneWork: contact.Phone,
                    co_PhoneCell: contact.MobilePhone,
                    co_Description: contact.Description,
                    co_SalesforceID: contact.Id
                  },
                  false,
                  function(err, obj) {
                    if (err) console.log(err);
                    status.Updated.push(obj.id);
                    console.log("Contact updated. SalesForeID: " +
                      obj.co_SalesforceID + " ContactName: " +
                      lr.isDefined(obj.co_Salutation) + " " +
                      lr.isDefined(obj.co_Name) + " " +
                      lr.isDefined(obj.co_Surname));
                  });
              }
            });
          callback(err);
        }, function(err) {
          if (err) console.error(err);
        });
      } else {
        console.log("Salesforce Connection Error!");
        status.Error = "Salesforce Connection Error";
      }
      return Promise.resolve(status);
    }).then(function(end) {
      cb(null, end);

    }).catch(function(err) {
      if (err) console.log(err);
    });
  };
  Contact.remoteMethod(
    'ImportContacts', {
      returns: {
        arg: 'result',
        type: 'string'
      },
      http: {
        path: '/importContacts',
        verb: 'get'
      }
    }
  );
};
Decretive answered 29/9, 2016 at 8:0 Comment(5)
You want to return what from where exactly within this wall of text?Exhortative
I want to return status variable from inside the conn.apex.get() and give it to cb() functionDecretive
Maybe you can try something like that for your solve: solve({status:status, callback:cb}); and that in your then block: .then(function(end) { end.callback(null, end.status); })Corley
after making changes application freeze and application gives error: "[TypeError: end.callback is not a function]" btw i forget to change and now fixed some code on return. solve => Promise.resolveDecretive
@Decretive Did my post below answer your question? If it did then you may consider accepting the answer because right now other people searching for this problem see that your question has no good answer and may not read it. If it didn't answer your question then please comment on what is missing. I'm going through my old answers and I want to make sure they are good. Thanks.Disinclined
D
1

It's not entirely clear what are asking about, and you don't include your solve() function which may be important here, so I can only give you some general tips.

You have something like this:

}).then(function(end) {
  cb(null, end);
}).catch(function(err) {
  if (err) console.log(err);
});

The first part (then) suggests that the cb() callback takes the error as the first argument and a value as the second argument, following the usual convention of Node callbacks.

But then in the second part (catch) you don't call the callback with the error. Also, the if (err) is redundant since in the catch handler there will always be an error, unless the solve() function returns a rejected promise with false or null specified as the rejection reason - and even then, whatever the rejection reason is, the callback should always be called in the case of error:

}).then(function(end) {
  cb(null, end);
}).catch(function(err) {
  console.log(err);
  cb(err);
});

That way you will not get a situation where the callback is never called and waits forever. When you mix promises with traditional callbacks you have to keep few things in mind:

Any function that gets a callback as an argument should make sure that this callback is called and that it is called exactly once. This is your responsibility as the function author to ensure that. In the case of error you should run:

callback(error);

and in the case of success you should call:

callback(null, data);

That way, the callback can know when the operation is finished and whether it finished with a success or failure by testing its first argument:

function (err, data) {
  if (err) {
    console.log('Error:', err);
  } else {
    console.log('Success:', data);
  }
}

The entire invocation of a function taking callback is usually:

functionTakingCallback('some', 'arguments', function (err, data) {
  if (err) {
    console.log('Error:', err);
  } else {
    console.log('Success:', data);
  }
});

On the other hand if the function returns a promise, you use it like this:

functionReturningPromise('some', 'arguments')
.then(function (data) {
  console.log('Success:', data);
})
.catch(function (err) {
  console.log('Error:', err);
});

No need for testing err in this case.

Callbacks should always be called exactly once. Promises should always be either resolved or rejected eventually. The usage is different and the responsibility of both the caller and the callee is different. When you mix those two styles - functions that take traditional Node-style callbacks and functions that return promises - then you have to be careful with those differences.

You can sometimes convert functions that take callbacks to functions that return promises using libraries like Bluebird and its promisify() and promisifyAll() to have consistent API for all your async functions in your entire code base. See:

You can see some other answers where I explain the difference between callbacks and promises and how to use them together in more detail, which may be helpful to you in this case:

Disinclined answered 29/9, 2016 at 8:47 Comment(1)
hi @Disinclined thanks about error control and callback usages. I've added missing code sorry about that :/ changed some code on return. solve => Promise.resolve I will change the code and try nowDecretive

© 2022 - 2024 — McMap. All rights reserved.