Q.ninvoke con la biblioteca node-soap evaluando la llamada a la función demasiado pronto
Pregunta
Estoy usando node-soap para integrarme con una API externa basada en SOAP.Con esta biblioteca, se crea un objeto de cliente en tiempo de ejecución basado en WSDL.Por lo tanto, el objeto del cliente SOAP no es válido en tiempo de diseño.Este es un problema al intentar utilizar la biblioteca de promesas Q.La biblioteca Q está vinculando/evaluando la llamada al método demasiado pronto, antes de que se defina.Aquí está el fragmento de código para ilustrar.
Este es el código del cliente que utiliza una cadena de promesa:
innotas.login(user,pass)
.then(innotas.getProjects())
.then(function () {
console.log('finished');
});
Este es el fragmento de código de servicio para iniciar sesión() que funciona bien.
this.login = function login (user, password) {
var deferred = q.defer();
// some stuff here
return self.createClient()
.then(function () {
self.innotasClient.login({ username: self.innotasUser, password: self.innotasPassword }, function(err, res) {
if (err) {
console.log('__Error authenticating to service: ', err);
deferred.reject(err);
} else {
self.innotasSessionId = res.return;
console.log('Authenticated: ', self.innotasSessionId);
deferred.resolve();
}
});
});
};
Este es el problema.self.innotasClient.findEntity no existe hasta después de CreateClient()
this.getProjects = function getProjects (request) {
// initiation and configuration stuff here
// CALL WEB SERVICE
self.innotasClient.findEntity(req, function findEntityCallback (err, response) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(response);
}
})
return deferred.promise;
// alternate form using ninvoke
return q.ninvoke(self.innotasClient, 'findEntity', req).then(function (response) {
// stuff goes here
}, function (err) {
// err stuff goes here
})
}
Este es el error de tiempo de ejecución:
self.innotasClient.findEntity(req, function findEntityCallback (err, r
^
TypeError: Cannot call method 'findEntity' of null
at getProjects (/Users/brad/Workspaces/BFC/InnotasAPI/innotas.js:147:28)
at Object.<anonymous> (/Users/brad/Workspaces/BFC/InnotasAPI/app.js:13:15)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
Este código funciona bien con devoluciones de llamada.¿Alguna idea de cómo hacer que esto funcione con la biblioteca de promesas?
Solución
La biblioteca Q está vinculando/evaluando la llamada al método demasiado pronto, antes de que se defina
No tu eres:
innotas.login(user,pass) .then(innotas.getProjects())
Aquí estás llamando getProject()
antes de pasar sus resultados al then
método.Sin embargo, then
espera un llamar de vuelta función, que se llamará cuando se resuelva la promesa.Usarías
innotas.login(user,pass).then(function(loginresult) {
innotas.getProjects()
})
Si el cliente no existe hasta el createClient
método produce, el cliente debe ser el resultado de esa función: ¡que devuelva una promesa para el cliente!
Entonces tu biblioteca debería verse así:
this.login = function login (user, password) {
// some stuff here
return self.createClient().then(function(client) {
return Q.ninvoke(client, "login", {
username: self.innotasUser,
password: self.innotasPassword
}).then(function(res) {
self.innotasSessionId = res.return;
console.log('Authenticated: ', self.innotasSessionId);
return client;
}, function(err) {
console.log('__Error authenticating to service: ', err);
throw err;
});
});
};
this.getProjects = function getProjects (client) {
// initiation and configuration stuff here
// CALL WEB SERVICE
return q.ninvoke(client, 'findEntity', req).then(function (response) {
// stuff goes here
}, function (err) {
// err stuff goes here
});
};