Standard Quality Standard Quality - 3 months ago 15
Javascript Question

Catch error from function within external script

I'm working with the Soundcloud API, but this question is about catching errors in general.

I try to load a track, and, due to some settings or restrictions specific to that track, get a

403 (Forbidden)
response. This error is thrown within the soundcloud script which I'm loading in my
<head>
:

<script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>


Later, in my client-side javascript:

SC.initialize({
client_id: 'xxxx',
});
...
SC.resolve(`https://soundcloud.com/${trackUrl}`).then((response) => {
this.track.setAttribute('src', `${response.stream_url}?client_id=xxxx`);
});


trackURL is a valid URL - it's the 'readable' url of the track, and it is resolving to the correct track ID, which I can see in the GET request error below:

In the console:

api.js:26 GET https://api.soundcloud.com/tracks/276705791.json?client_id=20f6b95488a0ca8f2254e250e6b0b229 403 (Forbidden)


inspecting api.js:
const sendRequest = (method, url, data, progress) => {
let xhr;
const requestPromise = new Promise((resolve) => {
const isFormData = global.FormData && (data instanceof FormData);
xhr = new XMLHttpRequest();

if (xhr.upload) {
xhr.upload.addEventListener('progress', progress);
}
xhr.open(method, url, true);

if (!isFormData) {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}

xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve({responseText: xhr.responseText, request: xhr});
}
};

xhr.send(data); // <-- LINE 26
});

requestPromise.request = xhr;
return requestPromise;
};


Since I'm loading this script externally, I can't fuss with it.

Is there any way to watch for errors within my own javascript so I can prepare a fallback?

Update

Joseph's answer below is what I needed - to look for the error in the
resolve
promise. Soundcloud isn't too helpful with response messages, but I can now program a fallback. Updated code:

SC.resolve('https://soundcloud.com/jacquesgreene/you-cant-deny').then((response) => {
this.track.setAttribute('src', `${response.stream_url}?client_id=20f6b95488a0ca8f2254e250e6b0b229`);
this.element.addClass('ready');
}, (error) => {
myFallback();
});

Answer

The easiest answer would be to consult the documentation.

Now this is XHR, which is asynchronous. You can't "catch" with your regular try-catch.

The xhr operation, however, only checks for readyState 4. means the xhr completed regardless of the HTTP status, even 403, and just resolves the promise with the data (responseText) and the xhr object itself (xhr). The problem now is if that resolved value goes back to your SC.resolve call.

From here, it's all a wild guess (unless, again, you consult the documentation). You can either inspect what response is in your callback, or try adding a reject callback in your call hope the API mapped it correctly as a failure.

SC.resolve(`https://soundcloud.com/${trackUrl}`).then((response) => {
    // What is `response` and what does it contain?
}, function(error){
    // Does this execute? If so, what is `arguments`.
});