如何使用Web Workers查找交集?

时间:2015-04-20 12:03:48

标签: javascript multithreading web-worker

我正在尝试使用Web Workers,但效果并不好。 我的实现不起作用,因为它没有以任何方式返回true,因为我认为结果总是错误的。当我找到第一个十字路口时,我该如何阻止所有工人? 所有工人也都工作很长时间,

这是我的代码

    // Delete all workers in previous iteration, because the don't need
    this.workers.forEach(function(worker, i){
        worker.terminate()
    });
    this.workers = [];
    var result = false;
    // For each line in polyline I create 4 workers for finding intersection with rectangle of selection
    for(var i=1; i<this.dots.length; ++i){
        if(result)
            return true;
        var handler = function(e){
            if(e.data.result){
                result = true;
            }
        };
        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: first_dot, l1p2: {x: second_dot.x, y: first_dot.y}, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: {x: second_dot.x, y: first_dot.y}, l1p2: second_dot, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: second_dot, l1p2: {x: first_dot.x, y: second_dot.y}, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

        this.workers.push(new Worker("js/intersection.js"));
        this.workers[this.workers.length-1].onmessage = handler;
        this.workers[this.workers.length-1].postMessage({type: "line_vs_line", l1p1: {x: first_dot.x, y: second_dot.y}, l1p2: first_dot, l2p1: {x: this.dots[i].dot.x, y: this.dots[i].dot.y}, l2p2: {x: this.dots[i-1].dot.x, y: this.dots[i-1].dot.y}});

    }
    return false;

该工作人员的代码:

onmessage = function(e){
    var l1p1 = e.data.l1p1;
    var l1p2 = e.data.l1p2;
    var l2p1 = e.data.l2p1;
    var l2p2 = e.data.l2p2;
    switch(e.data.type){
        case "line_vs_line":{
            var q = (l1p1.y - l2p1.y) * (l2p2.x - l2p1.x) - (l1p1.x - l2p1.x) * (l2p2.y - l2p1.y);
            var d = (l1p2.x - l1p1.x) * (l2p2.y - l2p1.y) - (l1p2.y - l1p1.y) * (l2p2.x - l2p1.x);
            if( d == 0 )
                postMessage({result: false});
            else{
                var r = q / d;
                q = (l1p1.y - l2p1.y) * (l1p2.x - l1p1.x) - (l1p1.x - l2p1.x) * (l1p2.y - l1p1.y);
                var s = q / d;
                postMessage({result: !( r < 0 || r > 1 || s < 0 || s > 1 )});
                console.log(r,s);
            }
            break;
        }
    }
};

1 个答案:

答案 0 :(得分:1)

在您进行函数调用时,您将完成所有工作,然后在结尾处返回false。无论你的功能如何,总会返回虚假。

您似乎误解了Javacript的Async工作流程。

var handler = function(e){
        if(e.data.result){
            result = true;
        }
    }  

在main函数返回false之后,上述函数才会执行。这是作为onmessage事件传递的,但它不是同步的,因此您无法修改结果&#39;并返回。

更好的方法是让一个单独的函数在一个工作完成时调出,一旦完成就完成你想要做的操作,或者在一个工作完成后传入一个回调函数来运行。

您的功能目前的工作原理如下:

  1. 杀死所有工作的员工

    this.workers.forEach(function(worker, i){
        worker.terminate()
    });
    this.workers = [];
    
  2. 将结果设为假

    var result = false;
    
  3. 对于每个点:检查Result(此时始终为false)旋转4个worker,并传入一个回调函数,当其中一个完成时,将result设置为true。

    for(var i=1; i<this.dots.length; ++i){
        if(result)
            return true;  
            // This will never happen as result is false for all loops at this point.
        var handler = function(e){
            if(e.data.result){
                result = true;
            }
        };
    //Etc, spin up 4 workers ... 
    
  4. 返回false(函数退出)

    return false;  
    // This always returns false,
    // nothing is stopping the function from getting here.
    
  5. 您的工作人员逐一完成并执行该功能,但是没有设置结果变量(所以它可能将全局变量设置为true)

    // Workers now execute this snippet one by one... 
    // but on the global scope, so result is going to be set globally, 
    // and not in your function.
    if(e.data.result){
        result = true;
    }
    
  6. 您无法对其执行任何操作,因为此时尚未执行任何其他功能。

  7. 这有意义吗?您无法以与同步工作流相同的方式考虑异步工作流。

    这是一篇关于异步的文章:http://recurial.com/programming/understanding-callback-functions-in-javascript/