Назначение значения?

0

У меня есть следующий код в services.js/Cordova

.factory('GCs', ['$http', function($http) {
        var obj= {};

        $http.post("mydomina.com?myrequest=getbyid", { "id": "1"} )
            .success(function(data) {
               obj= data; //there is a data returned correctly from the db
            })
            .error(function(data, status, headers, config) {
                return null;
            });
            console.log(obj); //obj is undefined?
        return {
            all: function() {
              return obj;
            }
        };
    }]);

Я пытаюсь вернуть json array (obj) из базы данных, однако этот obj не определен и, таким образом, я возвращаю null в методе (все), может ли кто-нибудь сказать мне причину почему?

благодаря

Теги:
cordova

1 ответ

1
Лучший ответ

У вас проблемы с синхронным и асинхронным кодом. Это немного усложнилось из-за того, что вы позволяете переменной, используемой асинхронным обратным вызовом, быть видимой для внешнего синхронного кода.

Рассмотрим, что происходит в этом примере кода.

function foo() {
    var bar = false;
    setTimeout(function () {
        bar = true;
        console.log(bar); // logs true
    }, 1000);
    console.log(bar); // logs false
    return {
        buzz: function () {
            return bar;
        }
    };
}

// see what we have
var fizz = foo();
// immediately
console.log(fizz.buzz()); // logs false
// .. wait >1 second
setTimeout(function () {
    console.log(fizz.buzz()); // logs true
}, 1500);

setTimeout в foo здесь похож на .success или .error в вашем коде

Итак, каковы решения вашей проблемы?

  • Используйте асинхронный обратный вызов для вызова последующих фрагментов кода
  • Пожарайте событие из вашего обратного вызова и прослушайте это событие, прежде чем продолжить работу с другими фрагментами кода (возможно, вам придется реализовать пользовательскую версию прослушивателей/обработчиков событий в зависимости от вашей среды)

Вот пример реализации событий вручную, это может быть немного избыточно для ваших нужд

function ObjectWithEvents(obj) {
    var handlers = Object.create(null);
    if (!obj) {
        if (this instanceof ObjectWithEvents) obj = this;
        else return new ObjectWithEvents();
    }
    Object.defineProperty(obj, 'addEventListener', {
        value: function (type, handler) {
            if (!(type in handlers)) handlers[type] = [];
            handlers[type].push(handler);
        }
    });

    Object.defineProperty(obj, 'removeEventListener', {
        value: function (type, handler) {
            var i;
            if (!(type in handlers)) return;
            i = handlers[type].indexOf(handler);
            if (i !== -1) handlers[type].splice(i, 1);
        }
    });

    Object.defineProperty(obj, 'dispatchEvent', {
        value: function (e) {
            var i, j, frozen_handlers;
            if (!(e.type in handlers)) return;
            frozen_handlers = handlers[e.type].slice();
            j = frozen_handlers.length;
            for (i = 0; i < j; ++i) {
                frozen_handlers[i].call(this, e);
                // if (e.cancelled) return;
            }
        }
    });
}
ObjectWithEvents.prototype = Object.create(Object.prototype);

И используя его с примером foo,

function foo() {
    var bar = false,
        ret_obj = new ObjectWithEvents();
    setTimeout(function () {
        bar = true;
        ret_obj.dispatchEvent({type: 'load'});
    }, 1000);
    ret_obj.buzz = function () {return bar;};
    return ret_obj;
}

var fizz = foo();

fizz.addEventListener('load', function () {
    console.log(fizz.buzz()); // logs true
});

Ниже приведен упрощенный пример того, как вы можете реализовать обратный вызов в своем текущем коде

.factory('GCs', ['$http', function($http) {
        var obj= {};

        $http.post("mydomina.com?myrequest=getbyid", { "id": "1"} )
            .success(function(data) {
               obj = data;
               code_needing_obj();
            })
            .error(function(data, status, headers, config) {
                // throw something so you know why the code stopped
                return null;
            });
        return {
            all: function() {
              return obj;
            }
        };
    }]);

function code_needing_obj() {
    // accessing .all here will give you obj
    // etc
}

Или даже переустановите весь свой код, чтобы HTTP-вызов был раньше всего

// make sure you have $http defined here
$http.post("mydomina.com?myrequest=getbyid", { "id": "1"} )
    .success(code_needing_obj) // this line lets invocation continue
    .error(function(data, status, headers, config) {
        // throw something so you know why the code stopped
    });

function code_needing_obj(obj) {
    // ...
    .factory('GCs', ['$http', function($http) {
            return {
                all: function() {
                  return obj;
                }
            };
        }]);
    // ...

}
  • 0
    Неправильно ли смешивать синхронные и асинхронные вызовы?
  • 0
    Не могли бы вы показать мне, что вы имеете в виду в моем коде для первого решения? Я все еще новичок с angularjs
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню