I'm using OpenLayers to draw a UK Ordnance Survey map. I have working examples, but they use a less secure method of accessing the UKOS servers by giving a key in the URL, whereas I'd like to use the more secure OAuth2 arrangement instead. To this end, I already have a CGI script querying the servers to get a session token, and returning this as JSON. The problem is making the map drawing page WAIT for its return, as follows:
UKOS.getToken = async function () {
if (
!UKOS.token ||
new Date().getTime() >
UKOS.token.issued_at + 1000 * (UKOS.token.expires_in - 15)
)
UKOS.token = await fetch(/* CGI Script */).then((response) =>
response.json()
);
console.log(UKOS.token.access_token);
return UKOS.token.access_token;
};
// ...
fetch(UKOS.WMTS + "&request=GetCapabilities&version=2.0.0", {
headers: { Authorization: "Bearer " + UKOS.getToken() },
}).then(/* etc */);
I have read that the explicit use of 'async' and 'await' shouldn't be necessary when using 'fetch', but their use definitely alters the behaviour, though neither version works, as follows:
With 'async' and 'await' as above:
Error messages come from the access token being returned as 'undefined' before it could be returned by the CGI script, but after these the console.log statement, which has waited for the token, prints the right answer.
Without these keywords:
The console.log prints undefined before the error messages resulting from the undefined return value.
This is being tested using FF 96.0.3, but PaleMoon 29.4.4.4 does the same, IE dies much earlier, I suspect because it doesn't understand modern scripting syntax.
How can I force the return to wait for the correct value?
async functions always return promises. So code like { Authorization: "Bearer " + UKOS.getToken() } is going to be trying to concatenate a string with a promise, which is not what you want. You need to either call .then on the promise and put your code in the callback:
UKOS.getToken()
.then(token => {
return fetch(UKOS.WMTS + "&request=GetCapabilities&version=2.0.0", {
headers: { Authorization: "Bearer " + token },
})
})
.then(/* etc */)
Or you need to put your code in an async function, and await the promise:
async function someFunction() {
const token = await UKOS.getToken();
const response = await fetch(UKOS.WMTS + "&request=GetCapabilities&version=2.0.0", {
headers: { Authorization: "Bearer " + token },
})
/* etc */
}