2016-05-08 15 views
7

Krom üzerinde bir web çalışanı başlattım ve setTimeout'u kullanarak tekrar tekrar çağrılan basit bir işlevi vardı. Şaşırtıcı bir şekilde, web çalışanı işlev yaklaşık 1000 kez çağrıldıktan sonra sona erdi. Nedenini açıklayan var mı? Sanırım krom biraz optimizasyon yapıyor. Turp Oluşturulamadığında : http://jsfiddle.net/meovfpv3/1/ O görünüyor uzun keyfi sürüyorWeb çalışanları aniden sona eriyor

var blob = new Blob([code]); 
var blobURL = window.URL.createObjectURL(blob); 
var worker = new Worker(blobURL); 
worker.onmessage = function(data) { 
    console.log(data.data); // gets called around 1000 times and done 
}; 

DÜZENLEME

webworker.js

function hi() { 
    postMessage('1'); 
    setTimeout(hi, 1); 
} 
hi(); 

main.js onmessage ca Bir kaç saniye kadar hızlı bir şekilde ateş etmeyi bırakacağız ve +5 dakika kadar uzunsa

+0

Tabii nedenini açıklayabilir, ama bunu tahmin etmemizi sormayın. Test etmek için ** minimum doğrulanabilir bir örnek ** göstermeniz gerekecek. –

+0

@IsmaelMiguel Soruyu worker.js koduyla güncelledim. Temelde ben bir dize dışında bir damla yapmak ve ben aynı sorunu yaşıyorum –

+0

işçiye verin. Ben İşçi (a 'console.log' ile test) sona olmadığını tespit ettik onMessage geri arama sadece bir noktada ateş olmak durdurur. Çok garip ve kabul edilemez bir tarayıcı davranışı! * masa çevirme * –

cevap

1

Her 1 ms'ye bir mesaj göndermeye mi çalışıyorsunuz? O zaman muhtemelen setInterval() kullanmak gerekiyordu:

setInterval(function(){ 
    postMessage('1'); 
}, 1); 

Düzenleme: Ben yanlış bunun arıyordu sırf yoktu özyinelemeye gördü. Yine de setTimeout üzerinden setInterval kullanırdım.

+1

fark nedir ? hi() '**, ** kendini tekrarlı olarak çağırmıyor. Kendisini tamamen farklı bir şey olarak geri çağırıyor. –

+0

Fark yoktur (ilgili olmayan bir performans farkı hariç). –

+0

@torazaburo Peki yaptığım utanç verici bir hata! Sanırım ana fark okunabilirlik mi ?! – Lesley

5

Neler olduğu hakkında en iyi tahminim. Her 1 ms'de bir Web Çalışanı'ndan bir mesaj göndererek, ana iş parçacığının her mesajın 1 ms içinde gönderilmesini talep ediyorsunuz. Ana iş parçacığı, iletiyi 1 ms içinde işleyemiyorsa, son iletiyi işlenmemiş olsa da yine de yeni bir ileti gönderiyorsunuz demektir. Bunun, işlenmeyi bekleyen mesajların kuyruğuna yerleştirdiğini düşünürdüm.

Artık web çalışanından işlenebileceklerinden daha hızlı mesajlar gönderiyorsunuz, işlenmemiş mesajların sırası daha da büyüyor. Bir noktada Chrome, ellerini fırlatacak ve "Kuyrukta çok fazla mesaj var" diyor ve işlemek için yeni mesajlar sıralamak yerine, bunları düşürüyor.

Bu nedenle, zaman aşımında 100 ms gibi makul bir sayı kullanırsanız, iletinin bir sonraki ileti gönderilmeden önce işlenmesi için çok zaman vardır ve işlenmemiş iletilerde sorun olmaz.


Ben işçi ana iş parçacığı bir mesaj gönderen bir jsFiddle oluşturduk ve ana iş parçacığı geri işçiye mesajı gönderir. Bir sonraki mesajın gönderilmesinden önce bu işlem gerçekleşmezse, her iki başlıktaki sayılar eşleşmez ve web çalışanı sonlandırılır. Sen 100ms makul bir setTimeout ile görebiliriz

http://jsfiddle.net/meovfpv3/3/

, tüm iletiler sonraki ileti oluşmadan önce işlemek için yeterli zamana sahip.

setTimeout öğesini 1 ms'ye düşürdüğünüzde, ileti zincirinin bir sonraki iletinin gönderilmesinden önce bitmesi ve her iş parçacığındaki sayaçların en sonunda, if maddesini durdurması ve web çalışanını sonlandırması gerekir.Bu sorunu gidermek için


bir yolu yerine körlemesine mesaj sonuncusu işlenen veya geri ana iş parçacığı bir mesaj aldıktan sonra, sadece yeni mesaj gönder yapılmadığının her 1 msn'de gönderme taşımaktadır. Bu, yalnızca ana iş parçacığının bunları işleyebildiği kadar hızlı bir şekilde iletileri gönderdiğiniz anlamına gelir.

İşçi:

var counter2 = 0; 
    var rcvd = true; 
    function hi() { 
    counter2++; 
    console.log("") 
    console.log("postMessage", counter2) 
    postMessage(counter2); 
    if (!rcvd) { 
     self.close(); 
     console.log("No message received"); 
    } 
    rcvd = false; 
    setTimeout(hi, 1); 
    } 
    hi(); 
    onmessage = function(e) { 
    rcvd = true; 
    console.log("secondMessage", e.data); 
    } 

Ana: Öncelikle

var ww = document.querySelector('script[type="text/ww"]'), 
    code = ww.textContent, 
    blob = new Blob([code], {type: 'text/javascript'}), 
    blobUrl = URL.createObjectURL(blob), 
    worker = new Worker(blobUrl), 
    counter = 0; 

worker.onmessage = function(e) { 
    counter++; 
    console.log("onmessage:", counter); 
    worker.postMessage(e.data); 
} 
+0

Ancak setTimeout aslında her milisaniyeyi yürütmez; en iyisi her 10-20 ms'de yürütür. –

+0

@torazaburo Doğru ama 'setTimeout', olabildiğince hızlı çalışacak ve oluşturduğu iletilerden daha hızlı bir şekilde işlenebiliyor. –

+0

Teşekkürler Max, ilginç bir teori. Ancak, orijinal kodum (OP'lerden farklı olan) 85ms'lik bir zaman aşımı kullanıyordu, bu yüzden teoriyi debug etmek için _seems_. Sorunun güvenilir bir şekilde üretildiği gibi, eklediğim orijinal jsfiddle'un da adaletli olduğundan emin değilim. Maalesef, gizli kullanım kodu olduğu için tüm kullanım durumumu kemanda sağlayamıyorum. Birisi problemi gösteremediği sürece nimet kazanacaksınız (Çabanız için!). Sorunun Chrome v50.2xx ile yeni olduğunu ve Web Worker optimizasyonları ile ilgili bir şey olduğunu sanıyorum. –

4

, gözlemlerin bir çift, ben açıklayamam burada Bütünlüğü için


JSFiddle code bir kopyasıdır ama ilginç biri ve birisi için ilham verici olabilir:

  • @Anson - Ben (hala Chrome'da) Codepen içine jsFiddle kodu koymak hiçbir sorun varsa. onmessage geri arama sadece çalışmaya devam ediyor!

  • Ve geri jsFiddle içinde ... Bir mesaj, ne kadar süre onmessage callback'inde önce var işçi mesajların alma sayısı değil bu yüzden bile 10s gibi uzun bir boşluk için setTimeout değişen başarısız ateş durur - olan çok fazla varyans.

    • işçiyi sonlandırır html bir düğme/bağlantı ve bir işleyici (jQuery kullanılan) ekleyin:

    Sonra bu özel örnekte hayatta onmessage işleyicisi tutmak için bazı yollar buldular tıklamada. Sadece bu kodu ekleyerek onu düzeltir. $("#stop").on("click",function(e){e.preventDefault();worker.terminate();});
  • onmessage tanımlandıktan sonra console.log(worker)'u ekleyin.
  • da basitçe onmessage tanımlayan sonra window.worker = worker ekleyebilir related question gönderilmiş bir cevap esinlenerek.

Her durumda tekrar worker'dan bahsetme ile ilgili bir şey onu canlı tutuyor gibi görünüyor.

+0

Elbette bu işe yarayacak. İşçiye referans var. Yani çöp toplanmayacak. –

İlgili konular