函数在angular中返回被拒绝的promise时传递给错误情况

时间:2017-01-17 17:08:57

标签: angularjs promise

我需要从js函数返回被拒绝的承诺。我正在使用角度$ q,你可以看到。但它没有用。

在函数getDBfileXHR中,当使用getDBfileXHRdeferred.reject()拒绝promise getDBfileXHRdeferred时,我将传递函数getDBfileXHR的错误情况并运行fallbackToLocalDBfileOrLocalStorageDB()。但它没有用。

是否存在语法错误? 我对承诺有点新意。

由于

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;
}

修改 我用approach重写了我的函数。它似乎更好,更清洁。但是现在你可以帮我处理多种尝试吗?

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();

    });
}

这是一种干净的方法,可以做几次尝试:

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();
    }
})

1 个答案:

答案 0 :(得分:0)

如果您删除代码重试(两次?)失败,您的代码可能会工作(没有查看) -

问题是,您的调用代码获得的唯一承诺是第一次尝试的承诺。如果第一次尝试失败,则该承诺永远不会被解决或拒绝

您需要使用getDBfileXHR(url, serverAttempts);返回的承诺解决承诺 - 例如

if (serverAttempts <= 2){
    sendErrorEmail("BL: jsonText is empty, trying to reach server another time", 11);
    getDBfileXHRdeferred.resolve(getDBfileXHR(url, serverAttempts));
    return;
} else {

因为如果promise(1)解析为被拒绝的promise(2),结果就是promise(1)拒绝promise(2)的拒绝值

这是原生Promises和许多Promise / A +兼容库的工作方式, 所以应该$.defer的情况,如果它遵循Promise / A + spec