有条件地在控制器中接收同步或异步对象(角度,离子)

时间:2016-03-25 15:06:31

标签: javascript angularjs asynchronous ionic-framework

我有以下控制器:

Sponsors.$inject = [];

function Sponsors() {

    var service = {
        all: all,
        allServer: allServer,
        allLocal: allLocal,
        get: get,
        getTimeStamp: getTimeStamp
    };
    return service;

    function all($http) {
        var timeDifference = (Date.now() - this.getTimeStamp());

        if (timeDifference < 600000) {
            return this.allLocal();
        }
        else {                
            return this.allServer($http);       
        }
    }

    function allServer($http) {
        return $http.get("http://dream16backend.azurewebsites.net/api/dream16/sponsors")
                    .then(function (resp) {
                        //Set localstorage, create timestamp and return the data
                        window.localStorage.setItem('sponsors', resp.data);
                        window.localStorage.setItem('sponsorsTimeStamp', Date.now());
                        var bla = JSON.parse(window.localStorage.getItem('sponsors'));
                        return bla;
                    }, function(err) {
                        console.log('ERR', err);
                    });            
    }

    function allLocal() {
        return JSON.parse(window.localStorage.getItem('sponsors'));
    }

    function get(adressId) {
        for (var i = 0; i < sponsors.length; i++) {
            if (sponsors[i].id === parseInt(sponsorId)) {
                return sponsors[i];
            }
        }
        return null;
    }

    function getTimeStamp() {           
        return window.localStorage.getItem('sponsorsTimeStamp');
    }
}

使用&#34;然后&#34;是因为我收到了一个异步对象。但是,我现在也可以通过以下服务接收同步对象: (功能(){     角         .module(&#39; sponsors.services&#39;,[])         .factory(&#39;赞助商&#39;,赞助商);

Sponsors.all(...).then is not a function

})(); 这样只有异步调用(函数allServer)才能工作,但同步失败,因为:else { this.allServer($http).then(function (data) { return data; }) }

然后我认为修复是移动&#34;然后&#34;功能到服务中的所有功能。这使得同步调用(函数allLocal)工作,但现在异步调用失败。其他条件现在看起来像这样:

.controller('SponsorsCtrl', function ($scope, Sponsors, $http) {
    $scope.$on('$ionicView.enter', function () {
        $scope.sponsors = Sponsors.all($http);
        var check = "check"; 
    });
})

控制器看起来像:

public class JavaFXApplication7 extends Application {

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Person> cb = new ComboBox();
        cb.setCellFactory(column -> new ListCell<Person>() {
            private HBox graphic = new HBox();
            private Label label1 = new Label() ;
            private Label label2 = new Label(" || ");
                private Label label3 = new Label();                
                {
                    graphic.getChildren().addAll(label1, label2, label3);
                }
            @Override
            public void updateItem(Person person, boolean empty) {
                if (person == null || empty) {
                    setGraphic(null);
                } else {
                    label1.setText(person.firstName.get());
                        label3.setText(person.email.get());
                    setGraphic(graphic);
                }
            }
        });

        ObservableList<Person> items = FXCollections.observableArrayList();
        Person p = new Person();
        p.email.set("foo@bar.com");
        p.firstName.set("Tony");
        p.lastName.set("Stark");
        p.phone.set("(555) 555-1212");

        items.add(p);
         Person p2 = new Person();
        p2.email.set("foo@bar.com");
        p2.firstName.set("Bruce");
        p2.lastName.set("Wayne");
        p2.phone.set("(444) 444-1212");

        items.add(p2);

        cb.setItems(items);

        StackPane root = new StackPane();
        root.getChildren().add(cb);        
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public class Person {
        StringProperty firstName = new SimpleStringProperty();
        StringProperty lastName = new SimpleStringProperty();
        StringProperty phone = new SimpleStringProperty();
        StringProperty email = new SimpleStringProperty();

        @Override
        public String toString () {
            return firstName.get() + " " + lastName.get();
        }

    }

}

我确认调用本身正在运行(通过测试变量&#34; bla&#34;)。我还看到控制器运行的控制器var check =&#34; check&#34 ;;在运行异步代码之前。我在这里做错了什么?

4 个答案:

答案 0 :(得分:1)

好的......所以你需要为Sponsors.all()的两个实例返回一个承诺,因为一个实例已经返回$http承诺。

在服务中注入$q,以便allLocal()也会返回一个承诺。

function allLocal() {
    return $q.resolve(JSON.parse(window.localStorage.getItem('sponsors')));
}

在控制器中,您需要使用then()

$scope.$on('$ionicView.enter', function () {
    Sponsors.all($http).then(function(data){
       $scope.sponsors = data;
    });
    var check = "check"; 
});

正如上面的评论中所提到的,没有必要在控制器中注入$http并将其传递给服务,只需在实际需要的地方注入$http更简单

答案 1 :(得分:1)

我建议您使用以下解决方案。在这两种情况下都返回“Promise”对象。对于allLocal函数,它将如下所示:

function allLocal() {
    var deferred = $q.defer();
    deferred.resolve(JSON.parse(window.localStorage.getItem('sponsors')));
    return deferred.promise;
}

所以现在你可以在两种情况下使用.then - sync和async

答案 2 :(得分:1)

我建议将$ http服务注入您的服务中...... I.e。

.factory('MyService', function ($http, $timeout,$q) {
    var service = {
            all: all,
            allServer: allServer,
            allLocal: allLocal,
            get: get,
            getTimeStamp: getTimeStamp
        };
        return service;

        function all() {
            var timeDifference = (Date.now() - this.getTimeStamp());

            if (timeDifference < 600000) {
                return this.allLocal();
            }
            else {                
                return this.allServer($http);       
            }
        }

        function allServer() {
            return $http.get("http://dream16backend.azurewebsites.net/api/dream16/sponsors")
                        .then(function (resp) {
                            //Set localstorage, create timestamp and return the data
                            window.localStorage.setItem('sponsors', resp.data);
                            window.localStorage.setItem('sponsorsTimeStamp', Date.now());
                            var bla = JSON.parse(window.localStorage.getItem('sponsors'));
                            return bla;
                        }, function(err) {
                            console.log('ERR', err);
                        });            
        }

        function allLocal() {
            var dfd = $q.defer();   //create a deferred object
            $timeout(function(){
               var localResponse = JSON.parse(window.localStorage.getItem('sponsors'));; 
               dfd.resolve(localResponse);   //resolve the localObject
            });
            return dfd.promise;  //return the promise object so controller gets the .then function
        }

        function get(adressId) {
            for (var i = 0; i < sponsors.length; i++) {
                if (sponsors[i].id === parseInt(sponsorId)) {
                    return sponsors[i];
                }
            }
            return null;
        }

        function getTimeStamp() {           
            return window.localStorage.getItem('sponsorsTimeStamp');
        }
})

答案 3 :(得分:0)

如果您正在处理可能会或可能不会返回承诺的服务,您可以使用$q.when(...)来包装该API调用,并让$q处理其余的调用。

在你的情况下,你所要做的就是像$q.when(Sponsors.all($http))一样包装你的服务API,并将它作为任何常规的承诺使用。

结帐https://github.com/kriskowal/q/wiki/API-Reference#promise-methods