2012-01-08 28 views
10

session timeout veya socket timeout gibi JavaScript bir timeout değil window.timeout ama bir şey uygulamak değil Nasıl - temelde - Bir "function timeout"JavaScript bir "fonksiyonu zaman aşımı" nasıl uygulanır - sadece 'setTimeout'

Önceden belirtilen başka bir olayı gerçekleşmedikçe, belirtilen bir olayın gerçekleşmesinden önce bir sistemde 'un geçmesine izin verilen belirli bir süre; her iki durumda da ya bir olay gerçekleştiğinde dönem sonlandırılır.

Özellikle, bir fonksiyonun yürütme zamanı gözlemlemek ve ulaşılması veya sonra observing timer duracaktır daha Belirli bir süre daha gidiyor eğer/yürütme işlevini bildirir bir javascript observing timer istiyorum.

Herhangi bir yardım büyük beğeni topluyor! Çok teşekkürler.

+0

[ 'Window.setTimeout (function_here, number_timeout_milliseconds) '] (https://developer.mozilla.org/en/DOM/window.setTimeout) ya da' window.setInterval'? –

+3

Yapılamaz, işlev bitene kadar kontrolü herhangi bir şeye iade etmez. – Esailija

cevap

12

Tam olarak ne sorduğunuzu açıklamıyorum, ama Javascript'in istediğiniz şekilde çalışmadığını düşünüyorum. Örneğin, normal bir işlev çağrısının, işlem tamamlanıncaya kadar veya belirli bir süre (hangisi önce gelirse) kadar devam ettirilemez. Bu javascript dışında uygulanabilir ve javascript ile (eşzamanlı ajax çağrıları ile yapıldığı gibi) maruz kalabilir, ancak düzenli işlevleri ile saf javascript içinde yapılamaz.

Diğer dillerden farklı olarak, Javascript tek bir iş parçacığıdır, böylece bir işlev yürütürken bir zamanlayıcı asla yürütmez (web çalışanları hariç, ancak yapabilecekleri çok çok sınırlıdır). Zamanlayıcı yalnızca işlev yürütüldüğünde yürütülür. Böylece, bir zamanlama fonksiyonu ile bir zamanlayıcı arasındaki bir ilerleme değişkenini bile paylaşamazsınız, böylece bir zamanlayıcının bir işlevin ilerleyişini "kontrol etmesi" için bir yol yoktur.

Kodunuz tamamen bağımsızdıysa (global değişkenlerinizden herhangi birine erişmediniz, diğer işlevlerinizi aramadılar ve yine de DOM'a erişmediler), sonra bir web sitesinde çalıştırabilirsiniz. çalışan (yalnızca yeni tarayıcılarda bulunur) ve ana iş parçacığında bir zamanlayıcı kullanın. Web çalışan kodu tamamlandığında, sonuçlarla ana konuya bir mesaj gönderir. Ana iş parçacığı bu mesajı aldığında, zamanlayıcıyı durdurur. Zamanlayıcı sonuçları almadan önce patlarsa, web çalışanını öldürebilir. Ancak, kodunuz web çalışanlarının kısıtlamaları ile yaşamak zorunda kalacaktı.

  1. ajax arama veya bir resmin yüklenmesi gibi bir zaman uyumsuz işlem başlatın: Böyle (onlar daha iyi JavaScript'ın tek iş parçacıklı-lık ile çalıştıkları için)

    Soemthing da asenkron işlemleri ile yapılabilir.

  2. Zaman aşımı süreniz için setTimeout() kullanarak bir zamanlayıcı başlatın.
  3. Zamanlayıcı, senkronize olmayan işleminiz tamamlanmadan önce patlarsa, senkronize olmayan işlemi durdurun (iptal etmek için API'leri kullanarak).
  4. Zamanlayıcı tetiklenmeden önce eşzamansız işlem tamamlanırsa, zamanlayıcıyı clearTimeout() ile iptal edin ve devam edin.

Örneğin, burada bir resmin yüklenmesi üzerine bir zaman aşımı koymak için:

function loadImage(url, maxTime, data, fnSuccess, fnFail) { 
    var img = new Image(); 

    var timer = setTimeout(function() { 
     timer = null; 
     fnFail(data, url); 
    }, maxTime); 

    img.onLoad = function() { 
     if (timer) { 
      clearTimeout(timer); 
      fnSuccess(data, img); 
     } 
    } 

    img.onAbort = img.onError = function() { 
     clearTimeout(timer); 
     fnFail(data, url); 
    } 
    img.src = url; 
} 
1

Yalnızca bazı hardcore hileler kullanarak bunu başarabilirsiniz."Değişken

var x = null; 

tanımlamak ve ayrı testi çalıştırın: örneğin gibi size fonksiyon döner neyi değişkenin tür biliyorsanız böyle bir şey deneyebilirsiniz (HER js fonksiyonu şey döndüren unutmayın, varsayılan undefined olan) iplik ":

function test(){ 
    if (x || x == undefined) 
     console.log("Cool, my function finished the job!"); 
    else 
     console.log("Ehh, still far from finishing!"); 
} 
setTimeout(test, 10000); 

ve son olarak çalıştırmak fonksiyonu:

x = myFunction(myArguments); 

Bu, yalnızca biliyorsan İşlevinizin herhangi bir değer döndürmediğini (örn. döndürülen değer undefined) veya döndürdüğü değer her zaman "yanlış değil", yani false deyimine (0, null vb. gibi) dönüştürülmez.

+0

Diğer dillerden farklı olarak Javascript, değişkenleri diğer yürütme işlevleri ile serbestçe paylaşabilen parçacıklara sahip değildir. Web çalışanlarına sahiptir, ancak değişkenleri paylaşarak değil sadece mesajlaşma yoluyla ana konu ile iletişim kurabilirler. – jfriend00

-1

observing timer ve executing function arasındaki bir değişkeni paylaşın.

observing timer'u window.setTimeout veya window.setInterval ile uygulayın. observing timer yürütüldüğünde, paylaşılan değişkene çıkış değerini ayarlar.

executing function sürekli değişken değerini denetler .. ve çıkış değerinin belirtilmesi durumunda döner.

+1

'setTimeout' sadece minimum gecikmeyi garanti eder, eğer zaman aşımı süresi dolduğunda' 'yürütme işlevi' hala çalışıyorsa, 'gözlem işlevi' yalnızca yürütme işlevi 'tamamlandığında çağrılır. Bu çözümü çalıştırmak için 'DoEvents' bir JS sürümünü uygulamanız gerekecek. – Douglas

+0

Javascript tek iş parçacıklı olduğundan, yürütme işlevi çalışırken bir zamanlayıcı asla çağrılmaz. Zamanlayıcı, işlev tamamlandıktan sonra SADECE tetiklenebilir. Bu yüzden, bunun işe yarayacağını düşünmüyorum. Aksini düşünüyorsanız, lütfen bunu gösteren bir jsFiddle oluşturun. – jfriend00

+0

Haklısınız. Bunu düşünün, eğer HTML5 bir seçenek ise, bir işçinin kullanımı olası bir çözüm olabilir. Ne düşünüyorsun? –

2

Kodu bir web çalışanında çalıştırabilirsiniz. Ardından kod çalışırken zaman aşımı olaylarını hala ele alabilirsiniz. Web çalışanı işini bitirir bitirmez, zaman aşımını iptal edebilirsiniz. Zaman aşımı gerçekleşir gerçekleşmez web çalışanını sonlandırabilirsiniz.

execWithTimeout(function() { 
    if (Math.random() < 0.5) { 
     for(;;) {} 
    } else { 
     return 12; 
    } 
}, 3000, function(err, result) { 
    if (err) { 
     console.log('Error: ' + err.message); 
    } else { 
     console.log('Result: ' + result); 
    } 
}); 

function execWithTimeout(code, timeout, callback) { 
    var worker = new Worker('data:text/javascript;base64,' + btoa('self.postMessage(' + String(code) + '\n());')); 
    var id = setTimeout(function() { 
     worker.terminate(); 
     callback(new Error('Timeout')); 
    }, timeout); 
    worker.addEventListener('error', function(e) { 
     clearTimeout(id); 
     callback(e); 
    }); 
    worker.addEventListener('message', function(e) { 
     clearTimeout(id); 
     callback(null, e.data); 
    }); 
}