Подтвердить что ты не робот

Как получить ответное сообщение REST в ExtJs 4?

Я основываюсь на пример RESTFul Store в ExtJs 4. Я хочу, чтобы мой script отображал ошибки, предоставляемые сервером REST, когда запрос "Добавить" или "Удалить" завершается с ошибкой. Мне удалось получить статус успеха запроса (см. Код ниже), но как мне добраться до сообщения, предоставленного с ответом?

Store:

    var store = Ext.create('Ext.data.Store', {
    model: 'Users',
    autoLoad: true,
    autoSync: true,
    proxy: {
        type: 'rest',
        url: 'test.php',
        reader: {
            type: 'json',
            root: 'data',
            model: 'Users'
        },
        writer: {
            type: 'json'
        },
        afterRequest: function(request, success) {
            console.log(success); // either true or false
        },
        listeners: { 
            exception: function(proxy, response, options) {

                // response contains responseText, which has the message
                // but in unparsed Json (see below) - so I think 
                // there should be a better way to reach it than 
                // parse it myself

                console.log(proxy, response, options); 
            }
        }
    }
});

Типичный ответ REST:

"{"success":false,"data":"","message":"VERBOSE ERROR"}"

Возможно, я делаю все неправильно, поэтому любые советы приветствуются.

4b9b3361

Ответ 1

Я предполагаю, что ваша служба соответствует принципу REST и использует коды состояния HTTP, отличные от 2xx для неудачных операций. Однако Ext не будет анализировать тело ответа для ответов, которые не возвращают статус OK 2xx. То, что объект исключения/ответа (который передается "слушателям событий исключения" ), обеспечивает в таких случаях только сообщение статуса HTTP в response.statusText.

Поэтому вам придется самостоятельно разобрать ответText на JSON. Это не проблема, поскольку она может быть выполнена с помощью одной строки.

var data = Ext.decode(response.responseText);

В зависимости от стиля кодирования вы также можете добавить некоторую обработку ошибок и/или провести различие между "ожидаемыми" и "неожиданными" кодами состояния HTTP-ошибок. (Это от Ext.data.reader.Json)

getResponseData: function(response) {
    try {
        var data = Ext.decode(response.responseText);
    }
    catch (ex) {
        Ext.Error.raise({
            response: response,
            json: response.responseText,
            parseError: ex,
            msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
        });
    }

    return data;
},

Причина такого поведения, вероятно, связана с тем, что прокси-класс REST не является членом первого класса в пакете данных. Он получен из общего базового класса, который также определяет поведение стандартного прокси-сервера AJAX (или JsonP), который использует коды состояния HTTP только для ошибок канала связи. Следовательно, в таких случаях они не ожидают сообщения с сервера с синтаксическим анализом. Ожидается, что ответы сервера, указывающие на ошибки приложения, будут возвращены с статусом HTTP "ОК" и ответ JSON, отправленный в ваш вопрос (с success:"false" и message:"[your error message]").

Интересно, что сервер REST мог возвращать ответ с статусом non-2xx и телом ответа с действительным ответом JSON (в терминах Ext), а свойство success - "true". Событие исключения будет по-прежнему запущено, а тело ответа не будет обработано. Эта настройка не имеет большого смысла - я просто хочу указать разницу между "успехом" в терминах кода состояния HTTP по сравнению с свойством success в теле (с первым преимуществом над последним).

Update

Для более прозрачного решения вы можете расширить (или переопределить) Ext.data.proxy.Rest: это изменит значение успеха от false до true, а затем вызовет стандартную реализацию processResponse. Это будет эмулировать "стандартное" поведение Ext и проанализировать responseText. Конечно, это ожидает стандартный ответ JSON, как указано в вашем исходном сообщении с помощью success:"false" (или иначе сбой). Однако это непроверено, и выражение if должно быть более умным.

Ext.define('Ext.ux.data.proxy.Rest', {
    extend: 'Ext.data.proxy.Rest',

    processResponse: function(success, operation, request, response, callback, scope){
        if(!success && typeof response.responseText === 'string') { // we could do a regex match here
            var args = Array.prototype.slice.call(arguments);
            args[0] = true;
            this.callParent(args);
        } else {
            this.callParent(arguments);
        }
    }
})