F.ninvoke mit Node-Soap-Bibliothek, die den Funktionsaufruf zu früh auswertet
Frage
Ich verwende Node-Soap, um eine externe Soap-basierte API zu integrieren.Mit dieser Bibliothek wird zur Laufzeit ein Client-Objekt auf Basis der WSDL erstellt.Daher ist das Soap-Clientobjekt zur Entwurfszeit nicht gültig.Dies ist ein Problem beim Versuch, die Q Promise-Bibliothek zu verwenden.Die Q-Bibliothek bindet / wertet den Methodenaufruf zu früh aus, bevor er definiert wird.Hier ist das Code-Snippet zur Veranschaulichung.
Dies ist der Client-Code, der eine Versprechen-Kette verwendet:
innotas.login(user,pass)
.then(innotas.getProjects())
.then(function () {
console.log('finished');
});
Dies ist das Servicecode-Snippet für login (), das einwandfrei funktioniert.
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();
}
});
});
};
Das ist das Problem.selbst.innotasClient.findEntity existiert erst nach 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
})
}
Dies ist der Laufzeitfehler:
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)
Dieser Code funktioniert gut mit Rückrufen.Irgendeine Idee, wie man das mit der Promise-Bibliothek zum Laufen bringt?
Lösung
Die Q-Bibliothek bindet / wertet den Methodenaufruf zu früh aus, bevor er definiert wird
Nein - du bist:
innotas.login(user,pass) .then(innotas.getProjects())
Hier rufst du an getProject()
bevor sie ihre Ergebnisse in die then
Methode.Jedoch, then
erwartet ein Callback funktion, die aufgerufen wird, wenn das Versprechen gelöst ist.Du würdest benutzen
innotas.login(user,pass).then(function(loginresult) {
innotas.getProjects()
})
Wenn der Client nicht existiert, bis die createClient
methode ergibt, sollte der Kunde der sein Ergebnis von dieser Funktion - lassen Sie es ein Versprechen für den Kunden zurückgeben!
Ihre Bibliothek sollte dann so aussehen:
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
});
};