Как я могу вернуть статус внутри обещания?

Я начал изучать обещание с loopback и jsforce и не мог справиться с этой проблемой; Я не мог вернуть статусную переменную внутри обещания функции cb(). В основном я хочу подключить salesforce и получить данные через JSforce и записать их в базу данных через обратную связь. Затем хотите вернуть созданные / обновленные / записи об ошибках клиенту после удаленного вызова.

Я разрабатываю с помощью Loopback с помощью Node.JS & Express.js. Я использую библиотеку JSforce для подключения к Salesforce.

Как я могу это исправить?

Вот мой код:

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'
      }
    }
  );
};

1 ответ

Не совсем понятно, о чем вы спрашиваете, и вы не включаете свой solve() функция, которая может быть важна здесь, поэтому я могу лишь дать вам несколько общих советов.

У вас есть что-то вроде этого:

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

Первая часть (then) предполагает, что cb() callback принимает ошибку в качестве первого аргумента и значение в качестве второго аргумента, следуя обычному соглашению обратных вызовов Node.

Но тогда во второй части (catchВы не перезвоните с ошибкой. Так же if (err) избыточно, так как в catch обработчик всегда будет ошибка, если только solve() функция возвращает отклоненное обещание с false или же null указывается в качестве причины отклонения - и даже тогда, какой бы ни была причина отклонения, обратный вызов всегда должен вызываться в случае ошибки:

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

Таким образом, вы не получите ситуацию, когда обратный вызов никогда не вызывается и ждет вечно. Когда вы смешиваете обещания с традиционными обратными вызовами, вы должны помнить о нескольких вещах:

Любая функция, которая получает обратный вызов в качестве аргумента, должна убедиться, что этот обратный вызов вызван и что он вызывается ровно один раз. Вы несете ответственность как автор функции за это. В случае ошибки вы должны выполнить:

callback(error);

и в случае успеха вам следует позвонить:

callback(null, data);

Таким образом, callback может узнать, когда операция завершена и закончилась ли она успехом или неудачей, проверив первый аргумент:

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

Полный вызов функции, выполняющей обратный вызов, обычно:

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

С другой стороны, если функция возвращает обещание, вы используете его следующим образом:

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

Нет необходимости в тестировании err в этом случае.

Обратные вызовы всегда должны вызываться ровно один раз. Обещания всегда должны быть либо выполнены, либо в конечном итоге отклонены. Использование отличается, и ответственность звонящего и вызываемого абонента различна. Когда вы смешиваете эти два стиля - функции, которые принимают традиционные функции обратного вызова в стиле Node, и функции, которые возвращают обещания, - вы должны быть осторожны с этими различиями.

Иногда вы можете конвертировать функции, которые принимают обратные вызовы, в функции, которые возвращают обещания, используя такие библиотеки, как Bluebird и его promisify() а также promisifyAll() иметь согласованный API для всех ваших асинхронных функций во всей вашей кодовой базе. Увидеть:

Вы можете увидеть некоторые другие ответы, в которых я объясню разницу между обратными вызовами и обещаниями и как их использовать более подробно, что может быть полезно для вас в этом случае:

Другие вопросы по тегам