我在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数组(obj),但是,这个obj是 undefined ,因此我在方法(全部)有谁可以告诉我原因?
由于
答案 0 :(得分: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;
}
};
}]);
// ...
}