Ich habe die folgende Funktion, um ein Objekt aus einer Datenbank abzurufen und eine URL zu extrahieren:
async redirect(id: string, redirectFunction: Function) {
if (!IdExists(id)) {
throw new Error(`ID ${id} does not exist.`);
}
const redirectLocation: string = await prisma.url.findUnique({
where: { uniqueId: id },
select: { url: true },
}).then((data) => {
return data?.url!;
});
redirectFunction('http://' + redirectLocation);
}
Die Funktion wird im folgenden Codeabschnitt aufgerufen:
app.get('/:id', async (req, res) => {
try {
redirectController.redirect(req.params.id, res.redirect);
} catch (error) {
console.error(error);
}
});
Ich bekomme jedoch die TypeError: Cannot read properties of undefined (reading 'location')
, ich sehe, dass der Fehler mit der res.redirect
Methode zusammenhängt. Wenn ich es jedoch console.log
zum Debuggen durch ersetze, wird die URL richtig angezeigt. Was kann diesen Fehler verursachen?
Lösung des Problems
Diese Codezeile:
redirectController.redirect(req.params.id, res.redirect);
Übergibt res.redirect
(eine Funktionsreferenz) als zweites Argument, aber alles, was übergeben wird, ist nur die Funktion, sodass die res
verloren geht, wenn Sie später versuchen, sie aufzurufen. Das führt dazu, dass die Methode bei der Ausführung einen falschen this
Wert hat und viele Dinge schief gehen.
Sie können das auf verschiedene Arten beheben. Einmal so ist mit .bind()
:
redirectController.redirect(req.params.id, res.redirect.bind(res));
.bind()
erstellt eine kleine Stub-Funktion, die sich den Wert von merkt, res
sodass die Stub-Funktion beim Aufruf mit der richtigen Referenz aufgerufen wird res
und somit der this
Wert innerhalb der Funktion korrekt ist.
Eine andere Möglichkeit, dies zu lösen, besteht darin, eine eigene kleine Stub-Funktion zu erstellen:
redirectController.redirect(req.params.id, (...args) => {
res.redirect(...args);
});
Wenn es Ihre Stub-Funktion aufruft, rufen Sie res.redirect()
es richtig auf und übergeben es mit allen Argumenten, mit denen der Controller Ihre Stub-Funktion aufgerufen hat.
Als kleine Demonstration können Sie diesen Effekt hier sehen:
const obj = {
greeting: "Hello",
talk: function() {
if (this && this.greeting) {
console.log(`this.greeting is "${this.greeting}"`);
} else {
console.log("value of this is wrong");
}
}
}
console.log("calling as obj.talk()");
obj.talk(); // works
console.log("-------------------------");
// function we pass a method to and then call that method
function callTalk(fn) {
fn();
}
console.log("calling by passing method to another function");
callTalk(obj.talk); // doesn't work
// call it using.bind()
console.log("-------------------------");
console.log("calling using.bind()");
callTalk(obj.talk.bind(obj)); // works
Keine Kommentare:
Kommentar veröffentlichen