2016-01-04 5 views
7

हम हमारे परियोजना में require.js का उपयोग कर रहे हैं और हम लाइन 705 में setTimeout ओवरराइड करने के लिए की जरूरत है, इस कोड को जो हम उपेक्षा/किसी भी तरह (सभी पर इस setTimeout छोड़करने की जरूरत है मेरा मतलब है कि इसे चलाने के लिए), समस्या यह है कि अगर मैं इसे ओपन सोर्स कोड में बदलता हूं तो स्पष्ट होता है कि जब मैं संस्करण बदलता हूं तो कोड खो जाएगा, मुझे इस सेट को ओवरराइड कैसे करना चाहिए केवल बाहर की आवश्यकता के लिए बाहर। Js फ़ाइल के लिए और इसे लंबे समय तक रखें जैसा कि मैं इस lib का उपयोग करता हूं, क्या यह वैश्विक स्तर पर जेएस में सुरुचिपूर्ण तरीके से करना संभव है?ओवरराइड setTimeout

https://github.com/jrburke/requirejs/blob/master/require.js

यह

 //If still waiting on loads, and the waiting load is something 
     //other than a plugin resource, or there are still outstanding 
     //scripts, then just try back later. 
     if ((!expired || usingPathFallback) && stillLoading) { 
      //Something is still waiting to load. Wait for it, but only 
      //if a timeout is not already in effect. 
      if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { 
       checkLoadedTimeoutId = setTimeout(function() { 
        checkLoadedTimeoutId = 0; 
        checkLoaded(); 
       }, 50); 
      } 
     } 
FYI करें

, कारण यह है कि हम इसे Chrome: timeouts/interval suspended in background tabs?

+0

यह मेरा अलार्म की घंटी के सभी बजाते, तुम क्यों यह करने के लिए की जरूरत है? वैश्विक कार्यों और वस्तुओं को बदलना * लगभग कभी नहीं * एक अच्छा विचार है। –

+0

@MadaraUchiha - लिंक जो मैंने सेटटामआउट के साथ प्रदान किया है, देखें जब हम निष्क्रिय टैब पर requ.js का उपयोग करते हैं (मेरा मतलब है कि नई विंडो खोलने के बाद) प्रत्येक सेवा लोड एक सेकंड लेता है !!! –

+0

लेकिन, यह एक निष्क्रिय टैब में है, उपयोगकर्ता नहीं देख रहा है, आप परवाह क्यों करते हैं कि यह कितना समय लगता है? –

उत्तर

5

आपने कहा है कि क्रोम पृष्ठभूमि में मौजूद टैब के लिए setTimeout पर क्रोम प्रदर्शन करता है जो थ्रॉटलिंग के आसपास काम करना है। मुझे नहीं लगता कि ऐसा करना एक अच्छा विचार है, लेकिन यदि आपको जरूरी है, तो आपको निश्चित रूप से setTimeout के साथ गड़बड़ करने की बजाय RequJS को पैच करना चाहिए।आप ने कहा:

अगर मैं खुले स्रोत कोड में परिवर्तन स्पष्ट मैं संस्करण में बदलाव होने पर कोड

यह सच केवल यदि आप परिवर्तन प्रदर्शन करने के लिए एक समझदार विधि का उपयोग नहीं करते है खो जाएगा । समझदारी से यह करना संभव है। उदाहरण के लिए, आप में require.js फ़ाइल स्थापित करने के लिए गुलप का उपयोग कर सकते हैं (npm के साथ आवश्यकताजेएस स्थापित करने के बाद) और build में एक पैच की गई फ़ाइल का उत्पादन करें। फिर आप अपने आवेदन में इस पैच की गई फ़ाइल का उपयोग करते हैं। यहाँ gulpfile.js है:

var gulp = require("gulp"); 

// Bluebird is a good implementation of promises. 
var Promise = require("bluebird"); 

// fs-extra produces a `fs` module with additional functions like 
// `ensureDirAsync` which is used below. 
var fs = require("fs-extra"); 

// Make it so that for each the function in fs that is asynchronous 
// and takes a callback (e.g. `fs.readFile`), a new function that 
// returns promise is created (e.g. `fs.readFileAsync`). 
Promise.promisifyAll(fs); 

var to_replace = 
"if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {\n\ 
        checkLoadedTimeoutId = setTimeout(function() {\n\ 
         checkLoadedTimeoutId = 0;\n\ 
         checkLoaded();\n\ 
        }, 50);"; 

var replace_with = 
"if (isBrowser || isWebWorker) {\n\ 
        checkLoaded();"; 


gulp.task("default", function() { 
    // Use `fs.ensureDirAsync` to make sure the build directory 
    // exists. 
    return fs.ensureDirAsync("build").then(function() { 
     return fs.readFileAsync("node_modules/requirejs/require.js") 
      .then(function (data) { 
       data = data.toString(); 

       // We use the split/join idiom to a) check that we get 
       // the string to be replaced exactly once and b) 
       // replace it. First split... 
       var chunks = data.split(to_replace); 

       // Here we check that the results of splitting the 
       // chunk is what we expect. 
       if (chunks.length < 2) { 
        throw new Error("did not find the pattern"); 
       } 
       else if (chunks.length > 2) { 
        throw new Error("found the pattern more than once"); 
       } 

       // We found exactly one instance of the text to 
       // replace, go ahead. So join... 
       return fs.writeFileAsync("build/require.js", 
             chunks.join(replace_with)); 
      }); 
    }); 
}); 

आप इसे चलाने से पहले npm install gulp fs-extra bluebird requirejs चलाने की जरूरत है। किसी भी दर पर, आप गुलप का उपयोग कर सकते हैं, आप ग्रंट का उपयोग कर सकते हैं, या आप किसी भी अन्य सिस्टम का उपयोग कर सकते हैं जिसे आप बनाना चाहते हैं। बिंदु हैं:

  1. आप RequireJS पैच करने के लिए एक प्रतिलिपि प्रस्तुत करने योग्य और स्वचालित विधि है। यदि आप npm के साथ RequJS का नया संस्करण स्थापित करते हैं, तो जब आप अपने सॉफ़्टवेयर का पुनर्निर्माण करते हैं तो पैच स्वचालित रूप से लागू होता है, जब तक कि आवश्यकताजेएस का कोड इस तरह से परिवर्तित नहीं होता है जो पैच लगाने से रोकता है। यदि कोई परिवर्तन पैच लगाने से रोकता है तो क्या होता है इसके लिए अगला बिंदु देखें।

  2. यह विधि रनटाइम पर setTimeout ओवरराइड करने से अधिक मजबूत है। मान लीजिए जेम्स बर्क checkLoaded से checkDone का नाम बदलने के लिए RequJS के एक नए संस्करण में निर्णय लेते हैं और संबंधित चर का नाम बदलते हैं (ताकि checkLoadedTimeoutIdcheckDoneTimeoutId बन जाए)। उपरोक्त gulpfile एक अपवाद उठाएगा जब आप इसे फिर से चलाते हैं क्योंकि यह टेक्स्ट को प्रतिस्थापित नहीं किया जाएगा। आपको प्रतिस्थापित करने के लिए टेक्स्ट को अपडेट करना होगा और प्रतिस्थापन ताकि पैच RequJS के नए संस्करण के साथ काम करे। यहां लाभ यह है कि आपको प्रारंभिक चेतावनी मिलती है कि चीजें बदल गई हैं और आपको पैच की समीक्षा करने की आवश्यकता है। आपको में देर से कोई आश्चर्य नहीं होगा, शायद आप अपने सॉफ्टवेयर का एक नया संस्करण ग्राहकों को पहले से ही वितरित कर चुके हैं।

    रन टाइम पर setTimeout ओवरराइड करने वाली विधियां चुपचाप अपनी नौकरी करने में विफल रहेंगी। वे एक ऐसे फ़ंक्शन की तलाश करेंगे जिसमें checkLoadedTimeoutId शामिल है, जो अब नए संस्करण में मौजूद नहीं होगा। इसलिए वे केवल RequJS को डिफ़ॉल्ट रूप से ऐसा करने का तरीका बताएंगे। विफलता एक सूक्ष्म होगा। (मैं एक परियोजना है कि 50 मॉड्यूल के ऊपर पर लोड होता है अनुकूलित नहीं के साथ setTimeout की प्रस्तावित कस्टम संस्करण के साथ RequireJS दौड़े हैं। मैं शेयर setTimeout का उपयोग कर RequireJS और RequireJS एक कस्टम setTimeout का उपयोग कर के बीच कोई प्रत्यक्ष अंतर देखा।)

  3. यह विधि setTimeout के हर उपयोग को धीमा नहीं करती है।setTimeout को RequJS की तुलना में अन्य कोड द्वारा उपयोग किया जाता है। कोई फर्क नहीं पड़ता कि आप इसे कैसे कट करते हैं, setTimeout पर एक कस्टम प्रतिस्थापन में कोड जोड़ना जो उस कार्य को पारित करने वाले प्रत्येक फ़ंक्शन में तारों की तलाश करना शुरू कर देता है सभीsetTimeout धीमे उपयोग करता है।

+0

सुरुचिपूर्ण विधि! इसे फ़ाइल को संपादित करने और सेटटाइमआउट को स्वयं बदलने की आवश्यकता नहीं है ... केवल एक पल जिसे आपको प्रोजेक्ट में गल्प/ग्रंट/अन्य कार्य प्रबंधित करने की आवश्यकता है। –

1

है क्या तुम सच में की जरूरत है इस ... लोड हो रहा है requirejs से पहले जोड़ने का प्रयास करें कर लाइन 705 है:

function isTimeoutIgnoredFunction(fn, time) { 
    // you should configure this condition for safety, to exclude ignoring different timeOut calls! 
    return time == 50 && fn.toString().indexOf('checkLoadedTimeoutId') > -1; 
} 

window.setTimeoutOriginal = window.setTimeout; 

window.setTimeout = function(fn, time) { 
    if (isTimeoutIgnoredFunction(fn, time)) { 
     return fn(); // or return true if you don't need to call this 
    } else { 
     return window.setTimeoutOriginal.apply(this, arguments); 
    } 
}; 

शो अंतिम क्रोम, फ़ायरफ़ॉक्स, आईई में उलड काम अगर कोई आवश्यकता नहीं प्रदान की गई है ... आपको समर्थित ब्राउज़र और minified require.js फ़ाइल के लिए "isTimeoutIgnoredFunction" फ़ंक्शन को फिर से लिखना होगा। लेकिन

console.log((function() { 
        checkLoadedTimeoutId = 0; 
        checkLoaded(); 
       }).toString()); 

कुछ ब्राउज़रों में यह सिर्फ "फंक्शन" की तरह कुछ कर सकते हैं:

देखने के लिए क्या स्ट्रिंग आप उपयोग कर सकते हैं।

आप नहीं कई setTimeout का है, तो यह उपयुक्त समाधान हो सकता है ...

2

आप setTimeout ओवरराइड और देखें कि क्या समारोह कॉलबैक के रूप में पारित require.js (checkLoadedTimeoutId) से है कि समारोह में इस्तेमाल एक चर शामिल कर सकते हैं। यदि हां, तुरंत कॉल करें, अन्यथा मूल setTimeout फ़ंक्शन कॉल करें।

(function(setTimeoutCopy) { 
    setTimeout = function(fn, timeout) { 
    if (fn.toString().indexOf("checkLoadedTimeoutId") >= 0) { 
     return fn(); 
    } else { 
     return setTimeoutCopy.apply(null, arguments); 
    } 
    }; 
}(setTimeout)); 

ध्यान दें कि इस कोड के साथ कई समस्याएं हैं। यदि आप setTimeout पर फ़ंक्शन पास करते हैं जिसमें checkLoadedTimeoutId है, तो इसे तुरंत निष्पादित किया जाएगा। इसके अलावा, अगर requ.js कोड को छोटा किया गया है और चर का नाम बदल दिया गया है, तो यह काम नहीं करेगा।

समेकित करने के लिए, ऐसा कोई अच्छा तरीका नहीं है। शायद आप जो चाहते हैं उसे प्राप्त करने के लिए एक अलग तरीका खोजने का प्रयास करें। इसके अलावा, कि बारे में पता होना के रूप में मादारा उचिहा ने कहा:

वैश्विक कार्य करता है और वस्तुओं को बदलने लगभग कभी नहीं एक अच्छा विचार है।

1

अन्य तरह से प्राप्त यह पुस्तकालय का एक ajax अनुरोध कर रही है और पैच यह पहले पुस्तकालय लोड करने के लिए है, लेकिन आप अनुरोध (वेनिला js या jQuery बनाने के लिए एक तरह से भरी हुई है की आवश्यकता होगी ...)

अगला कोड आवश्यकता को लोड करने का एक उदाहरण है और इसे डीओएम में लोड करने से पहले इसे regexp के साथ पैच करें।

$(function(){ 
 
    // here you can put the url of your own hosted requirejs or a url from a CDN 
 
    var requirejsUrl = 'https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js'; 
 
    
 
    function patch(lib){ 
 
    var toReplace = /if\s*\(\(isBrowser\s*\|\|\s*isWebWorker\)\s*\&\&\s*!checkLoadedTimeoutId\)\s*\{([^{}]|\{[^{}]*\})*\}/; 
 
    var by = 'if (isBrowser || isWebWorker) { checkLoaded();}'; 
 
    return lib.replace(toReplace, by); 
 
    } 
 
    
 
    $.get(requirejsUrl, function(lib){ 
 
    var libpatched = patch(lib); 
 
    
 
    var script=document.createElement('script'); 
 
    script.innerText=libpatched; 
 
    $('body').append(script); 
 
    
 
    console.log(window.require); // requirejs patched is loaded 
 
    }); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

+0

इस उत्तर में कोड RequJS को असीमित रूप से लोड करता है, जिसका अर्थ है कि आवश्यकता कोड पर निर्भर करता है कि किसी भी कोड को आवश्यकता से पहले RequJS उपस्थित होने की प्रतीक्षा करनी होगी। '' (एक सामान्य आम पैटर्न, जिसका उपयोग मैं करता हूं)। – Louis

संबंधित मुद्दे