Rumah  >  Artikel  >  hujung hadapan web  >  Penyelidikan tentang API berbilang benang pekerja web dalam kemahiran JavaScript_javascript

Penyelidikan tentang API berbilang benang pekerja web dalam kemahiran JavaScript_javascript

WBOY
WBOYasal
2016-05-16 16:28:391606semak imbas

HTML5 menyokong API seperti Web Worker, membenarkan halaman web melaksanakan kod berbilang benang dengan selamat. Walau bagaimanapun, Web Worker sebenarnya tertakluk kepada banyak batasan, kerana ia tidak boleh benar-benar berkongsi data memori dan hanya boleh membuat pemberitahuan status melalui mesej, jadi ia tidak boleh dipanggil "pelbagai benang" dalam erti kata sebenar.

Antara muka Web Worker sangat menyusahkan untuk digunakan Ia pada asasnya disertakan dengan kotak pasir, menjalankan fail js bebas dalam kotak pasir dan berkomunikasi dengan utas utama melalui postMessage dan onMessage:

Salin kod Kod adalah seperti berikut:

var worker = new Worker("my.js");
var bundle = {message:'Hello world', id:1};
worker.postMessage(bundle); //postMessage boleh menghantar objek bersiri
worker.onmessage = function(evt){
Console.log(evt.data); //Bandingkan objek yang dihantar semula daripada pekerja dengan objek dalam utas utama
console.log(bundle); //{message:'Hello world', id:1}
}

Salin kod Kod adalah seperti berikut:

//dalam my.js
onmessage = function(evt){
var data = evt.data;
Data.id ;
PostMessage(data); //{message:'Hello world', id:2}
}

Hasil yang diperolehi boleh didapati bahawa id data yang diperolehi dalam benang telah meningkat, tetapi selepas ia dihantar semula, id dalam berkas utas utama tidak berubah sebenarnya disalin, jadi Jika ya, utas tidak berkongsi data dan mengelakkan konflik baca dan tulis, jadi ia selamat. Harga untuk memastikan keselamatan benang adalah untuk mengehadkan keupayaan untuk memanipulasi objek benang utama dalam benang.

Mekanisme berbilang benang yang terhad ini sangat menyusahkan untuk digunakan. Kami pastinya berharap Worker dapat menyokong menjadikan kod tersebut kelihatan seperti ia mempunyai keupayaan untuk mengendalikan berbilang rangkaian pada masa yang sama berikut:

Salin kod Kod adalah seperti berikut:

var worker = ThreadWorker baharu(bundle /*shared obj*/);

worker.run(function(bundle){
//buat sth dalam thread pekerja...
This.runOnUiThread(function(bundle /*shared obj*/){
                  //lakukan sth dalam utas ui utama...
});
//...
});

Dalam kod ini, selepas kita memulakan pekerja, kita boleh membiarkan sebarang kod dijalankan dalam pekerja, dan apabila kita perlu mengendalikan utas ui (seperti membaca dan menulis DOM), kita boleh kembali ke utas utama untuk pelaksanaan melalui ini.runOnUiThread.

Jadi bagaimana untuk melaksanakan mekanisme ini? Lihat kod di bawah:

Salin kod Kod adalah seperti berikut:

function WorkerThread(sharedObj){
This._worker = new Worker("thread.js");
This._completes = {};
This._task_id = 0;
This.sharedObj = sharedObj;

var self = ini;
This._worker.onmessage = function(evt){
var ret = evt.data;
Jika(kembali__UI_TUGASAN__){
                    //jalankan pada tugas ui
          var fn = (Fungsi baharu("kembali " ret.__UI_TASK__))();
                 fn(ret.sharedObj);
         }lain{
                self.sharedObj = ret.sharedObj;
                diri._selesai[ret.taskId](ret);
}
}
}

WorkerThread.prototype.run = fungsi(tugas, selesai){
var _task = {__THREAD_TASK__:task.toString(), sharedObj: this.sharedObj, taskId: this._task_id};
This._completes[this._task_id ] = complete;
This._worker.postMessage(_task);
}

Kod di atas mentakrifkan objek ThreadWorker, yang mencipta Pekerja Web yang menjalankan thread.js, menyimpan objek kongsi SharedObj dan memproses mesej yang dihantar semula oleh thread.js.

Jika mesej UI_TASK dikembalikan daripada thread.js, kemudian jalankan fungsi yang diluluskan oleh mesej, jika tidak, laksanakan panggilan balik lengkap run Mari kita lihat cara thread.js ditulis:

Salin kod Kod adalah seperti berikut:

onmessage = function(evt){
var data = evt.data;

jika(data && data.__THREAD_TASK__){
        var task = data.__THREAD_TASK__;
         cuba{
               var fn = (Fungsi baharu("kembali " tugas))();

var ctx = {
threadSignal: benar,
tidur: fungsi(selang){
                                       ctx.threadSignal = palsu;
                          setTimeout(_run, interval);
                 },
                  runOnUiThread: fungsi (tugas){
PostMessage({__UI_TASK__:task.toString(), sharedObj:data.sharedObj});
                }
            }

fungsi _run(){
                  ctx.threadSignal = benar;
              var ret = fn.call(ctx, data.sharedObj);
PostMessage({error:null, returnValue:ret, __THREAD_TASK__:task, sharedObj:data.sharedObj, taskId: data.taskId});
            }

_run(0);

}tangkap(cth){
PostMessage({error:ex.toString(), returnValue:null, sharedObj: data.sharedObj});
}
}
}

Seperti yang anda lihat, thread.js menerima mesej daripada utas ui, yang paling penting ialah THREAD_TASK, iaitu "tugas" yang diluluskan oleh utas ui yang perlu dilaksanakan oleh utas pekerja Sejak fungsi itu tidak boleh bersiri, Apa yang diluluskan ialah rentetan Benang pekerja menghuraikan rentetan ke dalam fungsi untuk melaksanakan tugasan yang diserahkan oleh utas utama (perhatikan bahawa objek kongsi sharedObj dihantar semasa tugasan itu selesai). hasil pulangan dihantar ke utas ui melalui mesej. Mari kita lihat dengan lebih dekat Selain nilai pulangan returnValue, objek kongsi sharedObj juga akan dihantar kembali, kerana benang pekerja dan utas ui tidak berkongsi objek, kami menyegerakkan objek pada kedua-dua sisi melalui. tugasan (adakah thread ini selamat? ? Kenapa? )

Anda dapat melihat bahawa keseluruhan proses tidak rumit Selepas pelaksanaan ini, ThreadWorker ini boleh digunakan dalam dua cara berikut:

Salin kod Kod adalah seperti berikut:

var t1 = WorkerThread baharu({i: 100} /*shared obj*/);

        set Interval(function(){
            t1.run(function(sharedObj){
                    kembalikan sharedObj.i ;
                },
                fungsi(r){
                    console.log("t1>" r.returnValue ":" r.error);
                }
            );
        }, 500);
var t2 = Benang Pekerja baharu({i: 50});

        t2.run(function(sharedObj){  
            manakala(this.threadSignal){
                sharedObj.i ;

                this.runOnUiThread(function(sharedObj){
                    W("body ul").appendChild("

  • " sharedObj.i "
  • ");
                    });

                    this.sleep(500);
                }
                kembalikan sharedObj.i;
            }, fungsi(r){
                console.log("t2>" r.returnValue ":" r.error);
            });

    🎜

    好了,关于Pekerja Web的用法探讨就介绍到这里,有兴趣的同学可以去看一下下这个里,有兴趣的同学可以去看一下这个页https://gitkira目顬/Wkira个页.js (由于Worker需要用服务器测试,我特意在项目中放了一个山寨的httpd.js,是个非常简陋的http服务的js,直接用node就可从就可从。

    Kenyataan:
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn