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 09.02.2017 15:38

Цитата:

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

попробовал и получаю ошибку:

DOMException [DataCloneError: "The object could not be cloned."
code: 25
nsresult: 0x80530019
location: http://www.xxx.com/anguler-tasks-con...kers.min.js:1]


а если сделать так, то функция отрабатывает :

var param = { content: $fileContent, funcParseCSV: "function parseCSV(content) { console.log('ok'); } parseCSV();" };
angularWorker.run(obj);

а в воркере:

eval(input.funcParseCSV);


Но мне так не хотелось бы делать, т.к. лучше вариант - определить эту функцию внутри worker-a

destus 09.02.2017 16:35

okuznetsov1,
А, ну да, input -- сериализуемым оъектом должен быть, для ф-ции не подходит. Тогда твой 1 вариант, ок.

А зачем вообще эту ф-цию в scope объявлять и пытаться передавать? Может лучше сделать чистую функцию, объявить её в теле самого воркера и применять? А Content как раз передавать первым параметром run().

okuznetsov1 09.02.2017 17:20

Цитата:

Сообщение от destus (Сообщение 443803)
okuznetsov1,
А, ну да, input -- сериализуемым оъектом должен быть, для ф-ции не подходит. Тогда твой 1 вариант, ок.

А зачем вообще эту ф-цию в scope объявлять и пытаться передавать? Может лучше сделать чистую функцию, объявить её в теле самого воркера и применять? А Content как раз передавать первым параметром run().

Я вчера ещё объявил эту функцию в теле воркера и применял, всё работало и думал на этом варианте остановиться. Но поразмыслив, пришёл к выводу, что на всякий случай лучше передавать эту функцию в воркер, т.к. в ближайшем будущем в функционале системы могут появится ещё воркеры которые будут использовать эту же функцию, и придётся её дублировать.

вроде получилось как хотел, сделал так:

передаю в воркер:

var bodyFuncParseCSV = eval($scope.parseCSV).toString();
var param = { content: $fileContent, funcParseCSV: bodyFuncParseCSV };
return angularWorker.run(param);


в теле воркера вызываю так:

var Items = eval('var parseCSV = ' + input.funcParseCSV + '; parseCSV(input.content);');


Не знаю костыль это или нет, как вы считаете?

destus 09.02.2017 17:27

okuznetsov1,
обычно eval не рекомендуют к использованию.
Цитата:

в ближайшем будущем в функционале системы могут появится ещё воркеры которые будут использовать эту же функцию, и придётся её дублировать.
А что мешает выделить эту функцию в тело отдельного воркера и запускать его когда нужно? Т.е. сначала запускается воркер, который обладает функциональностью parseCSV, а когда он распарсит, в его коллбэке вызывать другой воркер, который будет делать http запрос на основе этих данных?

okuznetsov1 09.02.2017 18:53

Цитата:

Сообщение от destus (Сообщение 443810)
okuznetsov1,
обычно eval не рекомендуют к использованию.

А что мешает выделить эту функцию в тело отдельного воркера и запускать его когда нужно? Т.е. сначала запускается воркер, который обладает функциональностью parseCSV, а когда он распарсит, в его коллбэке вызывать другой воркер, который будет делать http запрос на основе этих данных?

Ваш данный вариант то что нужно. А не могли бы вы на небольшом примере показать как это реализовать (хотя бы схематично)? Я не могу разобраться как запустить второй воркер в коллбэке

destus 10.02.2017 06:41

okuznetsov1,
$scope.content = 'blabla';

var workerPromise1 = WorkerService.createAngularWorker(['input', 'output',   
    function(input, output) {  
		function parseCSV(input){
			/* body parseCSV */
			return parseInput
		}
		output.notify(parseCSV(input));
  }]);
  
var workerPromise2 = WorkerService.createAngularWorker(['input', 'output', '$http',   
    function(input, output, $http) {
		angular.forEach(input, 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]);
                                });
          });
  }]);
  
  workerPromise1.then(function success(angularWorker) {  
    //The input must be serializable  
    return angularWorker.run($scope.content);    
  }, function error(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) {  
    //handle result  
  }, function error(reason) {  
    //handle error  
  }, function notify(Items) {  
    workerPromise2.then(function(angularWorker){
		return angularWorker.run(Items)
	}).then(
		function(){},
		function(){},
		function notify(response){console.log(response)}
	) 
  });

okuznetsov1 10.02.2017 16:28

Цитата:

Сообщение от destus (Сообщение 443856)
okuznetsov1,
$scope.content = 'blabla';

var workerPromise1 = WorkerService.createAngularWorker(['input', 'output',   
    function(input, output) {  
		function parseCSV(input){
			/* body parseCSV */
			return parseInput
		}
		output.notify(parseCSV(input));
  }]);
  
var workerPromise2 = WorkerService.createAngularWorker(['input', 'output', '$http',   
    function(input, output, $http) {
		angular.forEach(input, 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]);
                                });
          });
  }]);
  
  workerPromise1.then(function success(angularWorker) {  
    //The input must be serializable  
    return angularWorker.run($scope.content);    
  }, function error(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) {  
    //handle result  
  }, function error(reason) {  
    //handle error  
  }, function notify(Items) {  
    workerPromise2.then(function(angularWorker){
		return angularWorker.run(Items)
	}).then(
		function(){},
		function(){},
		function notify(response){console.log(response)}
	) 
  });


Спасибо, очень мне помогли.

Но сейчас из всего вышесказанного у меня возник ещё один вопрос (наверное последний):

У меня возникла необходимость (как ранее я и предполагал) задействовать 2-ой воркер (workerPromise2) для расширения функционала системы. В свзи с этим возник вопрос - "как можно запустить второй воркер из другого контроллера", возможно ли такое? Сейчас я продублировал код 2-го воркера в другом контроллере. Но такое решение разумеется мне не нравится.
По сути в другом контроллере я разместил такой же код (что вы прислали в последнем сообщении), выглядит так:

app.controller('MainController', ['$scope', 'WorkerService', 'LxNotificationService', '$http', '$log', function($scope, WorkerService, LxNotificationService, $http, $log) {

    $scope.content = 'blabla';

    $scope.addContact = function() { 

         var workerPromise2 = WorkerService.createAngularWorker(['input', 'output', '$http',   
         function(input, output, $http) {
		angular.forEach(input, 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]);
                                });
                });
        }]);
  

        workerPromise2.then(function(angularWorker){
		return angularWorker.run(Items)
	}).then(
		function(){},
		function(){},
		function notify(response){console.log(response)}
	) 

    };

}]);

destus 10.02.2017 17:06

okuznetsov1,
А может лучше тогда в сервисе этот код воркера обьявить, инжектить сервис в каждый контроллер и оттуда вызывать?

okuznetsov1 20.02.2017 18:44

спасибо


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