У меня есть следующий код в 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 в методе (все), может ли кто-нибудь сказать мне причину почему?
благодаря
У вас проблемы с синхронным и асинхронным кодом. Это немного усложнилось из-за того, что вы позволяете переменной, используемой асинхронным обратным вызовом, быть видимой для внешнего синхронного кода.
Рассмотрим, что происходит в этом примере кода.
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;
}
};
}]);
// ...
}