如何使用 Web Worker 寻找交集?

How to use Web Workers for finding intersection?

我正在尝试使用 Web Worker,但效果不佳。 我的实现不起作用,因为它在任何方面都不 return 为真,因为我认为结果总是假的。当我找到第一个路口时,我应该如何阻止所有工人? 而且所有工人都工作很长时间,

这是我的代码

    // 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;
        }
    }
};

这里当你进行函数调用时,你会经历,创建你所有的工人,然后在最后 return false。不管你的函数是什么,总是return false。

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

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

在主函数已经 return 为 false 之前,上面的函数不会执行。这是作为 onmessage 事件传递的,但它不是同步的,因此您不能修改 'result' 和 return。

一个更好的方法是有一个单独的函数,一旦其中一个工作人员完成,你就会调用它来执行你想在某事完成后执行的操作,或者将回调函数传递给 运行 一次一名工人完成。

您的函数目前是这样工作的:

  1. 杀死任何正在工作的工人

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

    var result = false;
    
  3. 对于每个点:检查 Result(此时始终为 false)启动 4 个 worker,并传入一个回调函数,当其中一个完成时,将结果设置为 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. Return 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. 你不能用它做任何事情,因为此时没有其他函数在执行。

这有意义吗?您不能以与同步工作流相同的方式来考虑异步工作流。

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