Невозможно получить свойство «тогда» с помощью промисов

Я хочу, чтобы в моем приложении был максимально понятный код. Поэтому я решил отделить вызов xhr и синтаксический анализ от view.js. Для этого я добавил:

В View.js

this._pagePromises.push(myapp.Services.Foo.getFoo()
.then(
    function success(results) {
      var x = results;
    },
    function error() {
      // TODO - handle the error.
    }
));

И в Services.js

Foo:
{   
    getFoo: function () {
        WinJS.xhr({ url: "http://sampleurl.com" }).done(
            function completed(request) {
                //parse request
                var obj = myapp.Parser.parse(request);
                return obj;
            },
            function error(request) {
                // handle error conditions.
            }
        );  
    }
}

Но у меня есть это исключение:

0x800a138f — ошибка выполнения JavaScript: невозможно получить свойство «тогда» неопределенной или нулевой ссылки

Что я хочу, так это: запустите обещание в view.js, сделайте что-нибудь и обновите представление, когда getFoo() завершится. Я делаю это неправильно, но как разработчику С# мне трудно понять этот шаблон.

Изменить: есть мой обновленный код:

getFoo: function () {
var promise = WinJS.xhr({ url: myapp.WebServices.getfooUrl() });
    promise.done(
        function completed(request) {
            var xmlElements = request.responseXML;
            var parser = new myapp.Parser.foo();
            var items = parser.parse(xmlElements);
            return items;
        },
        function error(request) {
            // handle error conditions.
        }
    );
    return promise;
}

Это решило мою проблему с «тогда», но «обещание возврата» вызывается перед «возвратом элементов». Так что мой «звонящий» получает только обещание, а не его результат.

Что я упустил ?

Редактировать 2: есть правильный способ сделать это:

Foo:
{
    getFooAsync: function () {
        return WinJS.Promise.wrap(this.getXmlFooAsync().then(
            function completed(request) {

                var xmlElements = request.responseXML;
                var parser = new myapp.Parser.Foo();
                var items = parser.parse(xmlElements);
                return items;
            }
        ));  
    },

    getXmlFooAsync: function () {
      return WinJS.xhr({ url: "http://sampleurl.com" });
    }
}

person David    schedule 11.07.2013    source источник


Ответы (1)


Более компактный способ сделать это состоит в том, чтобы ваша функция возвращала возвращаемое значение из WinJS.xhr().then(). Это возвращает обещание, которое будет выполнено с возвращаемым значением вашего внутреннего завершенного обработчика:

Foo:
{
    getFooAsync: function () {
        return WinJS.xhr({ url: "http://sampleurl.com" }).then(
            function completed(request) {
                var xmlElements = request.responseXML;
                var parser = new myapp.Parser.Foo();
                var items = parser.parse(xmlElements);
                return items;
            }
        ));  
    },
}

Затем вызывающий объект может использовать then/done для обещания, которое он получает от getFooAsync, и результатом завершенного обработчика будут элементы, возвращенные завершенным обработчиком. (Вы не будете использовать .done внутри этой функции, потому что хотите вернуть обещание.)

Это заданное поведение then в Promises-A, позволяющее создавать цепочки. Подробнее об этом читайте в моем сообщении в блоге разработчиков Windows 8, http://blogs.msdn.com/b/windowsappdev/archive/2013/06/11/all-about-promises-for-приложениядлямагазинаWindows,написанныевjavascript.aspx.

person Kraig Brockschmidt - MSFT    schedule 11.07.2013
comment
Правда, так лучше. Спасибо. - person David; 12.07.2013