Javascript-форум (https://javascript.ru/forum/)
-   Angular.js (https://javascript.ru/forum/angular/)
-   -   Как в worker-е выполнить SQL-запрос? (https://javascript.ru/forum/angular/67277-kak-v-worker-e-vypolnit-sql-zapros.html)

okuznetsov1 07.02.2017 17:09

Как в worker-е выполнить SQL-запрос?
 
Реализовываю работу с воркером через сервисы ('ng-vkThread','ngWebworker'), в данном примере - 'ngWebworker', но ошибку получаю одну и тужу: ReferenceError: $http is not defined

Помогите, в с чем связана проблема?



app.js

var app = angular.module('contactList', ['lumx','ngSanitize', 'ngCsv', 'ng-vkThread','ngWebworker']);

app.controller('ReadFileController', ['$scope','$http','vkThread','Webworker', function ($scope, $http, vkThread, Webworker) {

                var foo = function (content) {

                                $http.post('/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'}).then(function(response) {


                        $scope.contactslist.push({
                                id: response.data[0].id,
                                last_name: response.data[0].last_name,
                                name: response.data[0].name,
                                patronymic_name: response.data[0].patronymic_name,
                                address: response.data[0].address,
                                telephone: response.data[0].telephone,
                                url: response.data[0].url,
                                description: response.data[0].description,
                                completed: response.data[0].completed
                        });


                });

                                return 1;
                }


        $scope.readContent = function($fileContent){

            $scope.content = $fileContent;

            var myWorker2 = Webworker.create(foo);
            myWorker2.run($scope.content).then(function(result) {
                console.log(result);
            });

        };

}]);

destus 07.02.2017 18:31

okuznetsov1,
Твой вебворкер запускается в другом потоке. То есть контекст воркера и ангуляр приложения полностью изолированы поэтому у тебя нет доступа к сервису $http.

Вот готовое решение https://github.com/FredrikSandell/angular-workers

okuznetsov1 08.02.2017 17:52

Цитата:

Сообщение от destus (Сообщение 443579)
okuznetsov1,
Твой вебворкер запускается в другом потоке. То есть контекст воркера и ангуляр приложения полностью изолированы поэтому у тебя нет доступа к сервису $http.

Вот готовое решение https://github.com/FredrikSandell/angular-workers


Реализовал по вашему решению, вроде бы получилось. Можете подсказать правильно ли сделал? Предполагаю, что есть ошибки, хотя код работает хорошо и без сбоев. Также как проверить что код работает в фоне? (я зацикливал на 1000 записей, а в это время щёлкал по странице и элементам, страница не подвешивалась и можно сказать не подтормаживала. может быть есть какие-то средства специальные для этого?)


var app = angular
            .module('contactList', ['lumx', 'ngSanitize', 'ngCsv', 'FredrikSandell.worker-pool'])
            .run(function (WorkerService) {
            //WorkerService.setAngularUrl('../bower_components/angular/angular.js');
            WorkerService.setAngularUrl('https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js');
            //WorkerService.addDependency(serviceName, moduleName, url);
        });

app.controller('ReadFileController', ['$scope', '$http', 'WorkerService', function ($scope, $http, WorkerService) {

        $scope.foo = function (content) {

            var workerPromise = WorkerService.createAngularWorker(['input', 'output', '$http', function (input, output, $http) {

                //var i=0;
                //var callback = function(i) {
                //  output.notify();
                //  i++;
                //};
                //for (var i = 0; i < 1000; i++) { callback(i); }
    
                output.notify();
            
            }]);

            workerPromise
                .then(function success(angularWorker) {
                    //The input must be serializable
                    return angularWorker.run();
                }, 
                function error(reason) {
                    console.log('callback error');
                    console.log(reason);
                    //for some reason the worker failed to initialize
                    //not all browsers support the HTML5 tech that is required, see below.
                }).then(function success(result) {
                    console.log('success');
                    console.log(result);
                    //handle result
                    }, function error(reason) {
                        //handle error
                        console.log('error');
                        console.log(reason);
                    }, function notify() {
                        //handle update


                        $http.post('/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'})
						  .then(function(response) {

							$scope.contactslist.push({
                                id: response.data[0].id,
                                last_name: response.data[0].last_name,
                                name: response.data[0].name,
                                patronymic_name: response.data[0].patronymic_name,
                                address: response.data[0].address,
                                telephone: response.data[0].telephone,
                                url: response.data[0].url,
                                description: response.data[0].description,
                                completed: response.data[0].completed
							});
							
						  }

                    }
                );
        }



	}]);

destus 08.02.2017 18:30

okuznetsov1,
:)
Код твоего воркера находится в строчках с 14 по 24. Как видишь, твой воркер синхронно возвращает уведомление что он завершил работу и твой http запрос выполняется в основном потоке, т.е. ничего полезного воркер тут не делает как видишь.

Я подозреваю, что ты хотел выполнять запросы в теле воркера, следовательно тебе надо перенести строку 48 в тело воркера и оттуда в then коллбеке уведомлять главный поток, что запрос завершен и можно обновлять состояние contactslist.

$http.post('/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'})
                          .then(function(response){
output.notify(response.data[0]);
})

function notify(data) {
...
}


Цитата:

может быть есть какие-то средства специальные для этого?)
Код создания воркера уже покрыт юнит тестами.

okuznetsov1 08.02.2017 19:44

Цитата:

Сообщение от destus (Сообщение 443681)
,
Я подозреваю, что ты хотел выполнять запросы в теле воркера, следовательно тебе надо перенести строку 48 в тело воркера и оттуда в then коллбеке уведомлять главный поток, что запрос завершен и можно обновлять состояние contactslist.

Да, в теле воркера. Я пробовал так как вы посоветовали, но получаю эту ошибку в Firefox: "Error: An invalid or illegal string was specified
rg/<@http://www.xxx.com/anguler-tasks-contacts/js/angular.min.js:106:201.........."


Если запускаю в Ghrome, то ошибка выглядит так: "XMLHttpRequest cannot load . Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource."


var app = angular
            .module('contactList', ['lumx', 'ngSanitize', 'ngCsv', 'FredrikSandell.worker-pool'])
            .run(function (WorkerService) {
            //WorkerService.setAngularUrl('../bower_components/angular/angular.js');
            WorkerService.setAngularUrl('https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js');
            //WorkerService.addDependency(serviceName, moduleName, url);
        });

app.controller('ReadFileController', ['$scope', '$http', 'WorkerService', function ($scope, $http, WorkerService) {

        $scope.foo = function (content) {

            var workerPromise = WorkerService.createAngularWorker(['input', 'output', '$http', function (input, output, $http) {

                //var i=0;
                //var callback = function(i) {
                //  output.notify();
                //  i++;
                //};
                //for (var i = 0; i < 1000; i++) { callback(i); }

                $http.post('/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'});

//                $http.post('/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'})
//                          .then(function(response){
//                            output.notify(response);
//                        });
            
            }]);

            workerPromise
                .then(function success(angularWorker) {
                    //The input must be serializable
                    return angularWorker.run();
                }, 
                function error(reason) {
                    console.log('callback error');
                    console.log(reason);
                    //for some reason the worker failed to initialize
                    //not all browsers support the HTML5 tech that is required, see below.
                }).then(function success(result) {
                    console.log('success');
                    console.log(result);
                    //handle result
                    }, function error(reason) {
                        //handle error
                        console.log('error');
                        console.log(reason);
                    }, function notify(response) {
                            //handle update
                            console.log(response.data[0]);
                    }
                );

        };

}]);

okuznetsov1 08.02.2017 21:42

С этим разобрался, проблема оказалась из за того, что нужно явно было указать "http://", т.е. так:

$http.post('http://www.xxx.com/anguler-tasks-contacts/addContactData.php',{last_name:1, name:2, patronymic_name:3, address:4, telephone:5, url:6, description:7, completed:'false'});

okuznetsov1 08.02.2017 21:56

Цитата:

Сообщение от destus (Сообщение 443681)
okuznetsov1,

Не понимаю как внутри workera вызвать $scope-функцию angular-приложения, т.е. мне нужно вызвать функцию ($scope.parseCSV(content)) ?


............

 $scope.foo = function (content) {

    var workerPromise = WorkerService.createAngularWorker(['input', 'output', '$http', function (input, output, $http) {


        var Items = parseCSV($content);

         angular.forEach(Items, function (value, key) {
                        $http.post('http://www.xxx.com/anguler-tasks-contacts/addContactData.php',{last_name:value[1], name:value[2], patronymic_name:value[3], address:value[4], telephone:value[5], url:value[6], description:value[7], completed:'false'})
                               .then(function(response){
                                    output.notify(response.data[0]);
                                });
          });

        }

    }

............

destus 09.02.2017 06:30

Цитата:

Не понимаю как внутри workera вызвать $scope-функцию angular-приложения, т.е. мне нужно вызвать функцию ($scope.parseCSV(content)) ?
One can not communicate data between worker and main thread by using service states. All communication must be done through the input object and output promise.

т.е. передавай функцию parseCSV в виде input.

okuznetsov1 09.02.2017 14:51

Цитата:

Сообщение от destus (Сообщение 443725)
One can not communicate data between worker and main thread by using service states. All communication must be done through the input object and output promise.

т.е. передавай функцию parseCSV в виде input.

т.е. мне нужно сделать как то так:

var param = new function() {
  this.content = content;
  this.funcParseCSV = "function parseCSV(input.content) { ........... }";
};


и передать в webworker:

return angularWorker.run(param);


а в worker-e уже как то так:

console.log( (new Function('', input.funcParseCSV))() );

destus 09.02.2017 15:03

okuznetsov1,
не понял этих костылей с new Function. Если мне надо передать просто функцию, то я её объявлю в основном потоке и передам параметром. А если нужно передать функцию и ещё что-то, то лучше сформировать объект и его передавать
var obj = {
  parseCSV: $scope.parseCSV,
  foo: 'bar'
}
angularWorker.run(obj)


Часовой пояс GMT +3, время: 10:32.