分配价值?

时间:2015-07-02 00:01:44

标签: javascript angularjs cordova

我在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 ,因此我在方法(全部)有谁可以告诉我原因?

由于

1 个答案:

答案 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;
                }
            };
        }]);
    // ...

}