I need to return a rejected promise from a js function. I am using Angular $q as you can see. But it doesn't work.
In function getDBfileXHR, when the promise getDBfileXHRdeferred is rejected using getDBfileXHRdeferred.reject()
I would to pass into the the error case of the function getDBfileXHR
and run fallbackToLocalDBfileOrLocalStorageDB(). But it doesn't work.
Is there a syntax error? I am a bit new to promises.
this.get = function () {
var debugOptionUseLocalDB = 0,
prodata = [],
serverAttempts = 0;
if (debugOptionUseLocalDB) {
return fallbackToLocalDBfileOrLocalStorageDB();
}
if (connectionStatus.f() === 'online') {
console.log("Fetching DB from the server:");
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
}, function () { // error
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
});
}
}
function getDBfileXHR(url, serverAttempts) {
var getDBfileXHRdeferred = $q.defer(),
request = new XMLHttpRequest();
if (typeof serverAttempts !== "undefined") serverAttempts++;
request.open("GET", url, true); //3rd parameter is sync/async
request.timeout = 2000;
request.onreadystatechange = function () { // Call a function when the state changes.
if ((request.readyState === 4) && (request.status === 200 || request.status === 0)) {
console.log('-we get response '+request.status+' from XHR in getDBfileXHR');
var jsonText = request.responseText.replace("callback(", "").replace(");", "");
if (jsonText === '') {
console.error('-error : request.status = ' + request.status + ', but jsonText is empty for url=' + url);
if (serverAttempts <= 2){
sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
getDBfileXHR(url, serverAttempts);
return;
} else {
sendErrorEmail("BL: jsonText is empty and attempted to reach server more than twice", 14);
var alertPopup = $ionicPopup.alert({
title: 'Error '+"11, jsonText is empty",
template: "Sorry for the inconvenience, a warning email has been sent to the developpers, the app is going to restart.",
buttons: [{
text:'OK',
type: 'button-light'
}]
});
getDBfileXHRdeferred.reject();
}
} else {
}
} else {
console.error('-error, onreadystatechange gives : request.status = ' + request.status);
getDBfileXHRdeferred.reject();
}
};
if (url === "proDB.jsonp") {
console.log("-Asking local proDB.json...");
} else {
console.log("-Sending XMLHttpRequest...");
}
request.send();
return getDBfileXHRdeferred.promise;
}
Edit
I rewrote my function using this approach. It seems better and cleaner like this. How can I now handle the multiple attempts?
function getDBfileXHR(url, serverAttempts) {
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open("GET", url, true); request.timeout = 2000;
var rejectdum;
if (url === "proDB.jsonp") {
console.log("-Asking local proDB.json...");
} else {
console.log("-Sending XMLHttpRequest...");
}
request.onload = function () {
if ( (request.readyState === 4) && (request.status === 200 || request.status === 0) ) {
console.log('-we get response '+request.status+' from XHR in getDBfileXHR');
var jsonText = request.responseText.replace("callback(", "").replace(");", "");
if (jsonText === '') {
console.error('-error : request.status = ' + request.status + ', but jsonText is empty for url=' + url);
sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
sendErrorEmail("BL: jsonText is empty and attempted to reach server more than twice", 14);
var alertPopup = $ionicPopup.alert({
title: 'Error '+"11, jsonText is empty",
template: "The surfboard database could not be updated, you won't see the new models in the list, sorry for the inconvenience.",
buttons: [{
text:'OK',
type: 'button-light'
}]
});
console.log('oui on passe rejectdum')
rejectdum = 1;
reject({
status: this.status,
statusText: request.statusText
});
} else {
var parsedJson;
try {
parsedJson = JSON.parse(jsonText);
} catch (e) {
console.warn("Problem when trying to JSON.parse(jsonText) : ");
console.warn(e);
console.warn("parsedJson :");
console.warn(parsedJson);
}
if (parsedJson) {
var prodata = jsonToVarProdata(parsedJson);
console.log('-writing new prodata to localStorage');
console.log('last line of prodata:' + prodata[prodata-1]);
storageService.persist('prodata', prodata);
storageService.store('gotANewDB', 1);
}
resolve(request.response);
dbReadyDeferred.resolve();
}
}
};
request.onerror = function () {
reject({
status: this.status,
statusText: request.statusText
});
};
request.send();
});
}
Is it a clean way to do this to do several attempts :
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
})
.catch(function (){
if (typeof serverAttempts !== "undefined") serverAttempts++;
console.log('on passe dans le catch, serverAttempts = ', serverAttempts)
if (serverAttempts < 2) {
return getDBfileXHR(dbUrl(), serverAttempts)
.then(function () { // success
console.log('-basic XHR request succeeded.');
return dbReadyDeferred.promise;
})
.catch(function (){
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
})
} else {
console.log("-basic XHR request failed, falling back to local DB file or localStorage DB...");
return fallbackToLocalDBfileOrLocalStorageDB();
}
})