SetTimeout (fn, 0) සමහර විට ප්‍රයෝජනවත් වන්නේ ඇයි?


897

මම මෑතකදී තරමක් අප්රසන්න දෝෂයකට ගොදුරු වී ඇති අතර, කේතය <select>ජාවාස්ක්‍රිප්ට් හරහා ගතිකව පටවනු ලැබේ . මෙම ගතිකව පටවන <select>ලද පූර්ව තෝරාගත් අගයක් තිබුණි. IE6, අප මේ වන විටත් කේතය තෝරාගත් විසින් අදාල කරුණ නිවැරදි කිරීමට ඇති <option>, සමහර විට නිසා <select>ගේ selectedIndexඅගය තෝරාගත් සමඟ සමපාත වේදැයි පිටතට වනු ඇත <option>s '' indexවිශේෂණය, පහත ලෙස:

field.selectedIndex = element.index;

කෙසේ වෙතත්, මෙම කේතය ක්‍රියා නොකරයි. ක්ෂේත්‍රය selectedIndexනිවැරදිව සකසා තිබුණද , වැරදි දර්ශකය තෝරා ගැනීම අවසන් වේ. කෙසේ වෙතත්, මම alert()නියම වේලාවට ප්‍රකාශයක් ඇලවූයේ නම් , නිවැරදි විකල්පය තෝරා ගනු ලැබේ. මෙය යම් ආකාරයක කාල ගැටළුවක් විය හැකි යැයි සිතමින්, මම මීට පෙර කේතයෙන් දුටු අහඹු දෙයක් උත්සාහ කළෙමි:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

මේක වැඩ කළා!

මගේ ගැටලුවට විසඳුමක් මා සතුව ඇත, නමුත් මෙය මගේ ගැටලුව විසඳන්නේ මන්දැයි මම හරියටම නොදනිමි. යමෙකුට නිල පැහැදිලි කිරීමක් තිබේද? මගේ ශ්‍රිතය “පසුව” ඇමතීමෙන් මම වළක්වා ගන්නේ කුමන බ්‍රව්සර ගැටළුවද setTimeout()?


2
බොහෝ ප්‍රශ්න එය ප්‍රයෝජනවත් වන්නේ මන්දැයි විස්තර කරයි. මෙය සිදුවන්නේ මන්දැයි ඔබට දැන ගැනීමට අවශ්‍ය නම් - මගේ පිළිතුර කියවන්න: stackoverflow.com/a/23747597/1090562
සැල්වදෝර් ඩාලි

18
පිලිප් රොබට්ස් සිය කතාවේදී මෙහි ඇති හොඳම ආකාරයෙන් මෙය පැහැදිලි කරයි. youtube.com/watch?v=8aGhZQkoFbQ
වාසා

ඔබ කඩිමුඩියේ සිටින්නේ නම්, ඔහු හරියටම ප්‍රශ්නය ඇසීමට පටන් ගන්නා වීඩියෝවේ කොටස මෙයයි: youtu.be/8aGhZQkoFbQ?t=14m54s . කෙසේ වෙතත්, මුළු වීඩියෝවම නැරඹීම වටී.
කයිල් ක්‍රෙස්කි

5
setTimeout(fn)සමාන වේ setTimeout(fn, 0), btw.
vsync

Answers:


848

ප්රශ්නය තුළ, අතර තරඟ තත්වයක් පැවතුනි:

  1. පතන ලැයිස්තුව ආරම්භ කිරීමට බ්‍රව්සරයේ උත්සාහය, එහි තෝරාගත් දර්ශකය යාවත්කාලීන කිරීමට සූදානම්, සහ
  2. තෝරාගත් දර්ශකය සැකසීමට ඔබේ කේතය

ඔබගේ කේතය නිරතුරුවම මෙම තරඟය ජය ගනිමින් බ්‍රව්සරය සුදානම් වීමට පෙර පතන තේරීම සැකසීමට උත්සාහ කරමින් සිටියේය, එයින් අදහස් වන්නේ දෝෂය දිස්වනු ඇති බවයි.

මෙම ධාවන තරඟය පැවතියේ ජාවාස්ක්‍රිප්ට් හි තනි ක්‍රියාත්මක කිරීමේ ත්‍රෙඩ් එකක් ඇති නිසා එය පිටු විදැහුම්කරණය සමඟ බෙදාගෙන ඇත. ජාවාස්ක්‍රිප්ට් ධාවනය කිරීමෙන් DOM යාවත්කාලීන කිරීම අවහිර කරයි.

ඔබේ කාර්යභාරය වූයේ:

setTimeout(callback, 0)

ඇමතුමකින් setTimeoutආයාචනා කිරීම සහ දෙවන තර්කය ලෙස බිංදුව කෙටිම ප්‍රමාදයකින් පසුව ඇමතුම අසමමුහුර්තව ක්‍රියාත්මක කිරීමට උපලේඛනගත කරනු ඇත - එය ටැබ් එක නාභිගත වූ විට සහ ක්‍රියාත්මක කිරීමේ ජාවාස්ක්‍රිප්ට් නූල් කාර්යබහුල නොවන විට මීටර් 10 ක් පමණ වේ.

OP හි විසඳුම වූයේ තෝරාගත් දර්ශකයේ සැකසුම මීටර් 10 ක් පමණ ප්‍රමාද කිරීමයි. මෙමඟින් බ්‍රවුසරයට DOM ආරම්භ කිරීමට දෝෂයක් ඇතිවිය.

ඉන්ටර්නෙට් එක්ස්ප්ලෝරර් හි සෑම සංස්කරණයක්ම විචක්ෂණශීලී හැසිරීම් ප්‍රදර්ශනය කළ අතර ඇතැම් විට මේ ආකාරයේ ක්‍රියාමාර්ග අවශ්‍ය විය. විකල්පයක් ලෙස එය OP හි කේත කේතයේ අව්‍යාජ දෝෂයක් විය හැකිය.


පිලිප් රොබට්ස්ගේ කතාව බලන්න "සිදුවීම් ලූපය කුමක්ද?" වඩාත් සවිස්තරාත්මක පැහැදිලි කිරීමක් සඳහා.


281
විසඳුම වන්නේ විදැහුම්කරණ නූල් අල්ලා ගැනීමට ඉඩ දීම සඳහා ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීම "විරාමයක්" කිරීමයි. ' සම්පුර්ණයෙන්ම සත්‍ය නොවේ, setTimeout කරන්නේ බ්‍රව්සර් සිදුවීම් පෝලිමට නව සිදුවීමක් එක් කිරීම සහ විදැහුම්කරණ එන්ජිම දැනටමත් එම පෝලිමේ ඇත (සම්පූර්ණයෙන්ම සත්‍ය නොවේ, නමුත් ප්‍රමාණවත් තරම් ආසන්නය) එබැවින් එය setTimeout සිදුවීමට පෙර ක්‍රියාත්මක වේ.
ඩේවිඩ් මෝල්ඩර්

48
ඔව්, එය වඩාත් සවිස්තරාත්මක හා වඩා නිවැරදි පිළිතුරකි. නමුත් උපක්‍රමය ක්‍රියාත්මක වන්නේ මන්දැයි ජනතාවට තේරුම් ගැනීමට මගේ “ප්‍රමාණවත් තරම් නිවැරදි” ය.
staticsan

2
Av ඩේවිඩ්මුල්ඩර්, එයින් අදහස් කරන්නේ බ්‍රව්සරය විග්‍රහ කිරීම සහ ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ නූල් වලින් වෙනස් ත්‍රෙඩ් එකක විදැහුම් කිරීමද?
ජේසන්

8
නැත, ඒවා ප්‍රතිපත්තිමය වශයෙන් එකම ත්‍රෙඩ් එකකින් විග්‍රහ කර ඇත. එසේ නොමැතිනම් DOM හැසිරවීමේ පේළි කිහිපයක් සෑම විටම ප්‍රත්‍යාවර්තයන් අවුලුවන අතර එය ක්‍රියාත්මක කිරීමේ වේගය කෙරෙහි අතිශයින්ම නරක බලපෑමක් ඇති කරයි.
ඩේවිඩ් මෝල්ඩර්

30
මෙම වීඩියෝව අප විසින් සකසා ඇත්තේ ඇයිද යන්න පිළිබඳ හොඳම පැහැදිලි කිරීම වේ 2014.jsconf.eu/speakers/…
davibq

672

පෙරවදන:

තවත් සමහර පිළිතුරු නිවැරදි නමුත් ඇත්ත වශයෙන්ම විසඳන්නේ ගැටලුව කුමක්ද යන්න නිදර්ශනය නොකරන්න, එබැවින් එම සවිස්තරාත්මක නිදර්ශනය ඉදිරිපත් කිරීම සඳහා මම මෙම පිළිතුර නිර්මාණය කළෙමි.

වැනි, මම දන්න කෙනෙක් ඉන්නවා සවිස්තරාත්මක ඇවිදින්න-හරහා බ්රව්සරය කුමක් කෙසේ භාවිතා setTimeout()උපකාරී වේ . එය දිගු පෙනුමක් ඇති නමුත් ඇත්ත වශයෙන්ම ඉතා සරල හා සරල ය - මම එය ඉතා සවිස්තරාත්මකව කළෙමි.

යාවත්කාලීන කිරීම: පහත පැහැදිලි කිරීම සජීවීව නිරූපණය කිරීම සඳහා මම JSFiddle එකක් සාදා ඇත: http://jsfiddle.net/C2YBE/31/ . එය ආරම්භ කිරීමට උදව් කිරීම ගැන hanThangChung ට බොහෝ ස්තූතියි .

UPDATE2: JSFiddle වෙබ් අඩවිය මිය ගියහොත් හෝ කේතය මකා දැමුවහොත්, මම මෙම පිළිතුරට අවසානයේ කේතය එක් කළෙමි.


විස්තර :

"යමක් කරන්න" බොත්තමක් සහ ප්‍රති .ලයක් සහිත වෙබ් යෙදුමක් ගැන සිතන්න.

මෙම onClick"යමක්" බොත්තම හසුරුවනු කරුණු 2 කරන්නේ වන කාර්යය "LongCalc ()", ඇමතුම්:

  1. ඉතා දිගු ගණනය කිරීමක් කරයි (කියන්න මිනිත්තු 3 ක් ගතවේ)

  2. ගණනය කිරීමේ ප්‍රති results ල ප්‍රති .ලයට මුද්‍රණය කරයි.

දැන්, ඔබේ පරිශීලකයින් මෙය පරීක්ෂා කිරීමට පටන් ගෙන, "යමක් කරන්න" බොත්තම ක්ලික් කරන්න, පිටුව එහි වාඩි වී විනාඩි 3 ක් කිසිවක් නොකරයි, ඔවුන් නොසන්සුන් වේ, බොත්තම නැවත ක්ලික් කරන්න, මිනිත්තු 1 ක් රැඳී සිටින්න, කිසිවක් සිදු නොවේ, නැවත බොත්තම ක්ලික් කරන්න ...

ගැටළුව පැහැදිලිය - ඔබට අවශ්‍ය වන්නේ "තත්වය" DIV ය, එය සිදුවන්නේ කුමක්ද යන්න පෙන්වයි. එය ක්‍රියාත්මක වන්නේ කෙසේදැයි බලමු.


එබැවින් ඔබ "තත්ව" ඩීඅයිවී (මුලින් හිස්) එකතු කර, කාරණා 4 ක් කිරීමට onclickහසුරුවන්නා (ශ්‍රිතය LongCalc()) වෙනස් කරන්න:

  1. "ගණනය කිරීම ... මිනිත්තු 3 ක් ගතවනු ඇත" යන තත්වය DIV තත්වයට පත් කරන්න

  2. ඉතා දිගු ගණනය කිරීමක් කරයි (කියන්න මිනිත්තු 3 ක් ගතවේ)

  3. ගණනය කිරීමේ ප්‍රති results ල ප්‍රති .ලයට මුද්‍රණය කරයි.

  4. "ගණනය කිරීම" තත්ත්වය DIV තත්වයට පත් කරන්න

තවද, ඔබ නැවත පරීක්ෂා කිරීම සඳහා යෙදුම සතුටින් පරිශීලකයින්ට ලබා දේ.

ඔවුන් නැවත ඔබ වෙත එන්නේ ඉතා කෝපයෙන්. ඔවුන් බොත්තම ක්ලික් කළ විට, DIV තත්ත්වය කිසි විටෙකත් "ගණනය කිරීම ..." තත්ත්වය සමඟ යාවත්කාලීන නොවූ බව පැහැදිලි කරන්න !!!


ඔබ ඔබේ හිස සීරීමට, ස්ටැක් ඕවර්ෆ්ලෝ වෙතින් විමසන්න (හෝ ලියකියවිලි හෝ ගූගල් කියවන්න), සහ ගැටලුව තේරුම් ගන්න:

බ්‍රව්සරය එහි සියලුම "TODO" කාර්යයන් (UI කාර්යයන් සහ JavaScript විධානයන්) සිදුවීම්වල ප්‍රති ing ලයක් ලෙස තනි පෝලිමකට දමයි . අවාසනාවකට මෙන්, නව "ගණනය කිරීම ..." අගය සමඟ "තත්වය" ඩීඅයිවී නැවත ඇඳීම පෝලිමේ අවසානයට යන වෙනම TODO වේ!

මෙන්න ඔබගේ පරිශීලකයාගේ පරීක්ෂණය අතරතුර සිදුවීම් බිඳවැටීම, එක් එක් සිදුවීමෙන් පසු පෝලිමේ අන්තර්ගතය:

  • පෝලිම්: [Empty]
  • සිදුවීම: බොත්තම ක්ලික් කරන්න. සිදුවීමෙන් පසු පෝලිම්:[Execute OnClick handler(lines 1-4)]
  • සිදුවීම: OnClick හසුරුවන්නාගේ පළමු පේළිය ක්‍රියාත්මක කරන්න (උදා: තත්වය DIV අගය වෙනස් කිරීම). උත්සවය පසු පෝලිමේ: [Execute OnClick handler(lines 2-4), re-draw Status DIV with new "Calculating" value]. DOM වෙනස්වීම් ක්ෂණිකව සිදුවන අතර, අනුරූප DOM මූලද්‍රව්‍යය නැවත ඇඳීම සඳහා ඔබට නව සිදුවීමක් අවශ්‍ය වන බව DOM වෙනස මගින් අවුලුවන ලද අතර එය පෝලිමේ අවසානයේ ඇති බව කරුණාවෙන් සලකන්න .
  • ගැටලුව!!! ගැටලුව!!! විස්තර පහත විස්තර කර ඇත.
  • සිදුවීම: හසුරුවන්නාගේ දෙවන පේළිය ක්‍රියාත්මක කරන්න (ගණනය කිරීම). පෝලිමේ පසු: [Execute OnClick handler(lines 3-4), re-draw Status DIV with "Calculating" value].
  • සිදුවීම: හසුරුවන්නාගේ 3 වන පේළිය ක්‍රියාත්මක කරන්න (ප්‍රති result ල DIV ජනගහනය කරන්න). පෝලිමේ පසු: [Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result].
  • සිදුවීම: හසුරුවන්නාගේ 4 වන පේළිය ක්‍රියාත්මක කරන්න ("DONE" සමඟ තත්වය DIV ජනගහනය කරන්න). පෝලිමේ: [Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value].
  • සිදුවීම: හෑන්ඩ්ලර් සබ් returnවෙතින් ගම්‍ය කරන්න onclick. අපි "ඔන්ක්ලික් හෑන්ඩ්ලර් ක්‍රියාත්මක කරන්න" පෝලිමෙන් ඉවතට ගෙන පෝලිමේ ඊළඟ අයිතමය ක්‍රියාත්මක කිරීමට පටන් ගනිමු.
  • සටහන: අපි දැනටමත් ගණනය කිරීම අවසන් කර ඇති බැවින්, පරිශීලකයා සඳහා මිනිත්තු 3 ක් ගතවී ඇත. නැවත දිනුම් ඇදීමේ සිදුවීම තවම සිදු නොවීය !!!
  • සිදුවීම: "ගණනය කිරීමේ" අගය සමඟ තත්ව DIV නැවත අඳින්න. අපි නැවත දිනුම් ඇද එය පෝලිමෙන් ඉවතට ගන්නෙමු.
  • සිදුවීම: ප්‍රති result ල අගය සමඟ ප්‍රති D ල DIV නැවත අඳින්න. අපි නැවත දිනුම් ඇද එය පෝලිමෙන් ඉවතට ගන්නෙමු.
  • සිදුවීම: "සිදු කරන ලද" අගය සමඟ තත්ව DIV නැවත අඳින්න. අපි නැවත දිනුම් ඇද එය පෝලිමෙන් ඉවතට ගන්නෙමු. තියුණු ඇස් ඇති නරඹන්නන්ට මයික්‍රෝ තත්පරයක භාගයක් සඳහා “ගණනය කිරීම” සහිත අගය දිදුලන තත්ත්වය DIV පවා දැක ගත හැකිය - ගණනය කිරීමෙන් පසුව

ඉතින්, යටින් පවතින ගැටළුව නම්, “තත්වය” ඩීඅයිවී සඳහා නැවත ඇඳීමේ සිදුවීම අවසානයේ පෝලිම් මත තැබීමයි, “ක්‍රියාත්මක කිරීමේ පේළිය 2” සිදුවීමෙන් පසුව මිනිත්තු 3 ක් ගත වේ, එබැවින් සැබෑ නැවත දිනුම් ඇදීම සිදු නොවේ ගණනය කිරීමෙන් පසුව.


ගලවා ගැනීමට පැමිණේ setTimeout(). එය උපකාර කරන්නේ කෙසේද? මක්නිසාද යත් දිගු කලක් ක්‍රියාත්මක වන කේතය ඇමතීමෙන් setTimeout, ඔබ සැබවින්ම සිදුවීම් 2 ක් නිර්මාණය කරයි: setTimeoutක්‍රියාත්මක කිරීමම සහ (කල් ඉකුත්වීම 0 නිසා), ක්‍රියාත්මක වන කේතය සඳහා වෙනම පෝලිම් ඇතුළත් කිරීම.

එබැවින්, ඔබේ ගැටළුව නිරාකරණය කිරීම සඳහා, ඔබ ඔබේ onClickහසුරුවන්නා දෙවරක් ප්‍රකාශයන් ලෙස වෙනස් කරයි (නව ශ්‍රිතයක හෝ ඇතුළත වාරණයක් onClick):

  1. "ගණනය කිරීම ... මිනිත්තු 3 ක් ගතවනු ඇත" යන තත්වය DIV තත්වයට පත් කරන්න

  2. ක්රියාත්මක setTimeout()0 කල් ඉකුත්වන හා ඇමතුමක් සමග LongCalc()කාර්යය .

    LongCalc()ශ්‍රිතය අවසාන වරට සමාන වන නමුත් පැහැදිලිවම "ගණනය කිරීම ..." තත්ත්වය DIV යාවත්කාලීන කිරීම පළමු පියවර ලෙස නොමැත; ඒ වෙනුවට ගණනය කිරීම වහාම ආරම්භ කරයි.

ඉතින්, සිදුවීම් අනුක්‍රමය සහ පෝලිම් දැන් මොන වගේද?

  • පෝලිම්: [Empty]
  • සිදුවීම: බොත්තම ක්ලික් කරන්න. සිදුවීමෙන් පසු පෝලිම්:[Execute OnClick handler(status update, setTimeout() call)]
  • සිදුවීම: OnClick හසුරුවන්නාගේ පළමු පේළිය ක්‍රියාත්මක කරන්න (උදා: තත්වය DIV අගය වෙනස් කිරීම). උත්සවය පසු පෝලිමේ: [Execute OnClick handler(which is a setTimeout call), re-draw Status DIV with new "Calculating" value].
  • සිදුවීම: හසුරුවන්නාගේ දෙවන පේළිය ක්‍රියාත්මක කරන්න (setTimeout ඇමතුම). පෝලිමේ පසු: [re-draw Status DIV with "Calculating" value]. තවත් තත්පර 0 ක් සඳහා පෝලිමේ අලුත් දෙයක් නොමැත.
  • සිදුවීම: වේලාව අවසන් වීමෙන් අනතුරු ඇඟවීම තත්පර 0 කට පසුව අක්‍රිය වේ. පෝලිමේ පසු: [re-draw Status DIV with "Calculating" value, execute LongCalc (lines 1-3)].
  • සිදුවීම: "ගණනය කිරීමේ" අගය සමඟ තත්ව DIV නැවත අඳින්න . පෝලිමේ පසු: [execute LongCalc (lines 1-3)]. අනතුරු ඇඟවීම ක්‍රියා විරහිත වීමට පෙර මෙම නැවත ඇඳීමේ සිදුවීම සත්‍ය වශයෙන්ම සිදුවිය හැකි බව කරුණාවෙන් සලකන්න.
  • ...

හුරේ! ගණනය කිරීම ආරම්භ කිරීමට පෙර DIV තත්ත්වය "ගණනය කිරීම ..." ලෙස යාවත්කාලීන විය !!!



මෙම උදාහරණ නිදර්ශනය කරමින් JSFiddle හි නියැදි කේතය පහත දැක්වේ: http://jsfiddle.net/C2YBE/31/ :

HTML කේතය:

<table border=1>
    <tr><td><button id='do'>Do long calc - bad status!</button></td>
        <td><div id='status'>Not Calculating yet.</div></td>
    </tr>
    <tr><td><button id='do_ok'>Do long calc - good status!</button></td>
        <td><div id='status_ok'>Not Calculating yet.</div></td>
    </tr>
</table>

JavaScript කේතය: (ක්‍රියාත්මක කර ඇති onDomReadyඅතර jQuery 1.9 අවශ්‍ය විය හැක)

function long_running(status_div) {

    var result = 0;
    // Use 1000/700/300 limits in Chrome, 
    //    300/100/100 in IE8, 
    //    1000/500/200 in FireFox
    // I have no idea why identical runtimes fail on diff browsers.
    for (var i = 0; i < 1000; i++) {
        for (var j = 0; j < 700; j++) {
            for (var k = 0; k < 300; k++) {
                result = result + i + j + k;
            }
        }
    }
    $(status_div).text('calculation done');
}

// Assign events to buttons
$('#do').on('click', function () {
    $('#status').text('calculating....');
    long_running('#status');
});

$('#do_ok').on('click', function () {
    $('#status_ok').text('calculating....');
    // This works on IE8. Works in Chrome
    // Does NOT work in FireFox 25 with timeout =0 or =1
    // DOES work in FF if you change timeout from 0 to 500
    window.setTimeout(function (){ long_running('#status_ok') }, 0);
});

12
නියම පිළිතුර DVK! මෙන්න ඔබේ උදාහරණය නිරූපණය කරන සාරාංශයක් gist.github.com/kumikoda/5552511#file-timeout-html
kumikoda

4
ඇත්තෙන්ම සිසිල් පිළිතුර, ඩීවීකේ. සිතීම පහසු කිරීම සඳහා, මම එම කේතය jsfiddle jsfiddle.net/thangchung/LVAaV
thangchung

4
HaThangChung - JSFiddle හි වඩා හොඳ අනුවාදයක් (බොත්තම් 2 ක්, එක් එක් සිද්ධිය සඳහා එකක්) සෑදීමට මම උත්සාහ කළෙමි. එය ක්‍රෝම් සහ අයිඊ හි නිරූපණයක් ලෙස ක්‍රියා කරන නමුත් කිසියම් හේතුවක් නිසා එෆ්එෆ් මත නොවේ - jsfiddle.net/C2YBE/31 බලන්න . : මම FF මෙතන වැඩ කරන්නේ නැහැ ඇයි කියා ඇසූ stackoverflow.com/questions/20747591/...
DVK

1
VDVK "බ්‍රව්සරය සිය" TODO "කාර්යයන් (UI කාර්යයන් සහ JavaScript විධානයන් දෙකම) සිදුවීම්වල ප්‍රති ing ලයක් ලෙස තනි පෝලිමකට දමයි". සර් ඔබට කරුණාකර මේ සඳහා මූලාශ්‍රය ලබා දිය හැකිද? විවිධ UI (විදැහුම්කරණ එන්ජිම) සහ JS නූල් තිබිය යුතු යැයි කියන Imho arent බ්‍රව්සර් .... කිසිදු වරදක් අදහස් නොකෙරේ .... ඉගෙන ගැනීමට අවශ්‍යය ..
bhavya_w

1
habhavya_w නැත, සියල්ල සිදුවන්නේ එක නූල් එකක ය. දිගු js ගණනය
කිරීමකින්

88

ජාවාස්ක්‍රිප්ට් ටයිමර්ස් ක්‍රියා කරන ආකාරය පිළිබඳ ජෝන් රෙසිග්ගේ ලිපිය බලන්න . ඔබ කල් ඉකුත් වූ විට, එන්ජිම වත්මන් ඇමතුම් තොගය ක්‍රියාත්මක කරන තෙක් එය අසමමුහුර්ත කේතය පෝලිම් කරයි.


25

බ්‍රව්සර් සතුව "ප්‍රධාන නූල්" නමින් ක්‍රියාවලියක් ඇත, එය සමහර ජාවාස්ක්‍රිප්ට් කාර්යයන් ක්‍රියාත්මක කිරීම සඳහා වගකිව යුතු ය, යූඅයි යාවත්කාලීන කිරීම් උදා: පින්තාරු කිරීම, නැවත ඇඳීම, නැවත පිරවීම යනාදිය. ක්‍රියාත්මක කළා. ප්‍රධාන නූල කාර්යබහුල වන අතර UI යාවත්කාලීන කිරීම් ජනනය කරන විට, කාර්යයන් පණිවිඩ පෝලිමට එකතු වේ.


"සෑම ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමක් සහ යූඅයි යාවත්කාලීන කිරීමේ කාර්යයන් බ්‍රව්සර් සිදුවීම් පෝලිම් පද්ධතියට එකතු කරනු ලැබේ. ඉන්පසු එම කාර්යයන් බ්‍රවුසරයේ ප්‍රධාන යූඅයි ත්‍රෙඩ් වෙත යවනු ලැබේ." .... මූලාශ්‍රය කරුණාකර?
bhavya_w

4
ඉහළ කාර්යසාධනය ජාවාස්ක්‍රිප්ට් (නිකලස් සකාස්, ස්ටොයාන් ස්ටෙෆනොව්, රොස් හාම්ස්, ජූලියන් ලෙකොම්ට් සහ මැට් ස්වීනී)
ආර්ලි

මේ සඳහා පහත් කරන්න add this fn to the end of the queue. වැදගත්ම දෙය නම් setTimeoutමෙම විනෝදය, මෙම ලූප චක්‍රයේ අවසානය හෝ ඊළඟ ලූප චක්‍රයේ ආරම්භය හරියටම එකතු කරන ස්ථානයයි .
හරිත

22

setTimeout() 0 ලෙස සකසා තිබුණද, DOM මූලද්‍රව්‍ය පූරණය වන තෙක් ඔබ යම් කාලයක් මිලදී ගනී.

මෙය පරීක්ෂා කරන්න: setTimeout


19

මෙහි එකිනෙකට පරස්පර විරෝධී පිළිතුරු ඇති අතර, සාක්ෂි නොමැතිව කවුරුන් විශ්වාස කළ යුතු දැයි දැන ගැනීමට හැකියාවක් නැත. VDVK නිවැරදි බවත් alSalvadorDali වැරදි බවත් මෙහි සාක්ෂි වේ. දෙවැන්න මෙසේ කියයි:

"මෙතැනදී ඇයි: මිලි තත්පර 0 ක ප්‍රමාදයකින් සෙට් ටයිමූට් ලබා ගත නොහැක. අවම අගය බ්‍රව්සරය විසින් තීරණය කරනු ලබන අතර එය මිලි තත්පර 0 ක් නොවේ. Ically තිහාසිකව බ්‍රව්සර් මෙම අවම මිලි තත්පර 10 දක්වා සකසයි, නමුත් HTML5 පිරිවිතර සහ නවීන බ්‍රව්සර් එය මිලි තත්පර 4 කින් සකසා ඇත.

4ms අවම කල් ඉකුත්වීම සිදුවෙමින් පවතින දෙයට අදාල නොවේ. සැබවින්ම සිදුවන්නේ සෙට් ටයිම out ට් විසින් ඇමතුම් ලබා ගැනීමේ කාර්යය ක්‍රියාත්මක කිරීමේ පෝලිමේ අවසානය දක්වා තල්ලු කිරීමයි. SetTimeout පසු (ඇමතුම් ආපසු, 0) ඔබට අවහිර කිරීමේ කේතයක් තිබේ නම් එය ක්‍රියාත්මක වීමට තත්පර කිහිපයක් ගත වේ, අවහිර කිරීමේ කේතය අවසන් වන තුරු තත්පර කිහිපයක් සඳහා ඇමතුම ක්‍රියාත්මක නොවේ. මෙම කේතය උත්සාහ කරන්න:

function testSettimeout0 () {
    var startTime = new Date().getTime()
    console.log('setting timeout 0 callback at ' +sinceStart())
    setTimeout(function(){
        console.log('in timeout callback at ' +sinceStart())
    }, 0)
    console.log('starting blocking loop at ' +sinceStart())
    while (sinceStart() < 3000) {
        continue
    }
    console.log('blocking loop ended at ' +sinceStart())
    return // functions below
    function sinceStart () {
        return new Date().getTime() - startTime
    } // sinceStart
} // testSettimeout0

ප්‍රතිදානය:

setting timeout 0 callback at 0
starting blocking loop at 5
blocking loop ended at 3000
in timeout callback at 3033

ඔබේ පිළිතුරෙන් කිසිවක් ඔප්පු නොවේ. එය පෙන්නුම් කරන්නේ ඔබේ යන්ත්‍රය යටතේ විශේෂිත තත්වයක් යටතේ පරිගණකය ඔබට අංක කිහිපයක් විසි කරන බවයි. සම්බන්ධ යමක් ඔප්පු කිරීමට ඔබට කේත පේළි කිහිපයකට හා සංඛ්‍යා කිහිපයකට වඩා ටිකක් අවශ්‍ය වේ.
සැල්වදෝර් ඩාලි

6
Al සැල්වදෝර්ඩාලි, මගේ සාක්ෂිය බොහෝ දෙනෙකුට තේරුම් ගත හැකි තරම් පැහැදිලි බව මම විශ්වාස කරමි. මම හිතන්නේ ඔබට ආරක්ෂිත බවක් දැනෙන අතර එය තේරුම් ගැනීමට උත්සාහයක් ගෙන නොමැත. එය පැහැදිලි කිරීමට උත්සාහ කිරීම ගැන මම සතුටු වෙමි, නමුත් ඔබ තේරුම් ගැනීමට අසමත් වන්නේ කුමක්දැයි මම නොදනිමි. මගේ ප්‍රති .ල ඔබ සැක කරන්නේ නම් ඔබේ පරිගණකයේ කේතය ධාවනය කිරීමට උත්සාහ කරන්න.
ව්ලැඩිමීර් කෝර්නියා

අන්තිම වතාවට එය පැහැදිලි කිරීමට මම උත්සාහ කරමි. මගේ පිළිතුර වන්නේ කල් ඉකුත් වීමේ, කාල පරතරයේ ඇති සිත්ගන්නාසුලු ගුණාංග කිහිපයක් පැහැදිලි කිරීම සහ වලංගු සහ හඳුනාගත හැකි ප්‍රභවයන්ගෙන් හොඳින් සහාය වීමයි. එය වැරදියි කියා ඔබ ප්‍රබල ප්‍රකාශයක් කළ අතර යම් හේතුවක් නිසා ඔබ සාක්ෂියක් නම් කළ ඔබේ කේත කැබැල්ලට යොමු කළේය. ඔබගේ කේත කැබැල්ලේ කිසිදු වරදක් නොමැත (මම එයට විරුද්ධ නැත). මම කියන්නේ මගේ පිළිතුර වැරදියි කියලා. එය කරුණු කිහිපයක් පැහැදිලි කරයි. මම මේ යුද්ධය නවත්වන්න යන්නේ මට කාරණයක් නොපෙනෙන බැවිනි.
සැල්වදෝර් ඩාලි

16

එය කිරීමට එක් හේතුවක් වන්නේ කේතය ක්‍රියාත්මක කිරීම වෙනම, පසුව සිදුවීම් ලූපයකට කල් දැමීමයි. කිසියම් ආකාරයක බ්‍රව්සර් සිදුවීමකට ප්‍රතිචාර දක්වන විට (මූසික ක්ලික් කිරීම, උදාහරණයක් ලෙස), සමහර විට මෙහෙයුම් සිදු කිරීම අවශ්‍ය වන්නේ වත්මන් සිදුවීම සැකසූ පසුව පමණි . මෙම setTimeout()පහසුකම එය කිරීමට පහසුම ක්රමය වන්නේ.

දැන් සංස්කරණය කරන්න එය 2015 බව මම සටහන් කළ යුතුයි requestAnimationFrame(), එය හරියටම සමාන නොවන නමුත් එය setTimeout(fn, 0)සඳහන් කිරීම වටී.


මෙය හරියටම එය භාවිතා කරන බව මා දුටු ස්ථාන වලින් එකකි. =)
සයිබොට්

FYI: මෙම පිළිතුර stackoverflow.com/questions/4574940/…
Shog9

2
වෙනම, අනතුරු පුඩුවක් කිරීමට කේතය ඝාතනය නොකර ගන්නා ලෙසද වේ : ආකාරය ඔබ තෙරුම් කරන්නේ අනතුරු පුඩුවක් ? වත්මන් සිදුවීම් ලූපයක් යනු කුමක්දැයි ඔබ හඳුනා ගන්නේ කෙසේද? ඔබ දැන් සිටින්නේ කුමන සිදුවීම් ලූපයකදැයි ඔබ දන්නේ කෙසේද?
හරිත

හරිත හොඳයි, ඔබ එසේ කරන්නේ නැහැ. ජාවාස්ක්‍රිප්ට් ධාවන කාලය කුමක් දැයි සෘජු දෘශ්‍යතාවයක් නොමැත.
පොයින්ටි

requestAnimationFrame විසින් IE සහ Firefox සමහර විට UI යාවත්කාලීන නොකිරීමේ ගැටලුව විසඳීය
ඩේවිඩ්

9

මෙය පැරණි පිළිතුරු සහිත පැරණි ප්‍රශ්න වේ. මට අවශ්‍ය වූයේ මෙම ගැටළුව පිළිබඳව නව පෙනුමක් එක් කිරීමට සහ මෙය සිදුවන්නේ ඇයිද යන්න සහ මෙය ප්‍රයෝජනවත් වන්නේ ඇයිද යන්නට පිළිතුරු දීමටය.

එබැවින් ඔබට කාර්යයන් දෙකක් ඇත:

var f1 = function () {    
   setTimeout(function(){
      console.log("f1", "First function call...");
   }, 0);
};

var f2 = function () {
    console.log("f2", "Second call...");
};

ඉන්පසු f1(); f2();දෙවැන්න පළමුව ක්‍රියාත්මක කළ බව බැලීමට පහත දැක්වෙන අනුපිළිවෙලට ඔවුන් අමතන්න .

මෙන්න මෙන්න හේතුව: setTimeoutමිලි තත්පර 0 ක ප්‍රමාදයක් තිබිය නොහැක . මෙම අවම අගය බ්රව්සරය මගින් තීරණය කරනු අතර එය 0 තත්පර නොවේ. Ically තිහාසිකව බ්‍රව්සර් මෙම අවම මිලි තත්පර 10 දක්වා සකසයි, නමුත් HTML5 පිරිවිතර සහ නවීන බ්‍රව්සර් එය මිලි තත්පර 4 ක් ලෙස සකසා ඇත.

කැදැල්ල මට්ටම 5 ට වඩා වැඩි නම් සහ කල් ඉකුත් වීම 4 ට වඩා අඩු නම්, කල් ඉකුත් වීම 4 දක්වා වැඩි කරන්න.

මොසිල්ලා වෙතින් ද:

නවීන බ්‍රව්සරයක 0 ms කල් ඉකුත් වීමක් ක්‍රියාත්මක කිරීමට, ඔබට මෙහි විස්තර කර ඇති පරිදි window.postMessage () භාවිතා කළ හැකිය .

ප්‍රා.ලේ. තොරතුරු ඊළඟ ලිපිය කියවීමෙන් පසුව ගනු ලැබේ .


1
@ user2407309 ඔබ විහිළු කරනවාද? ඔබ අදහස් කළේ HTML5 පිරිවිතර වැරදියි සහ ඔබ නිවැරදිද? ඔබ අවතක්සේරු කිරීමට පෙර ප්‍රභවයන් කියවා ශක්තිමත් හිමිකම් පෑමක් කරන්න. මගේ පිළිතුර HTML පිරිවිතර හා historical තිහාසික වාර්තා මත පදනම් වේ. එකම දේ නැවත නැවතත් පැහැදිලි කරන පිළිතුර කරනවා වෙනුවට, මම අලුත් දෙයක් එකතු කළෙමි, පෙර පිළිතුරු වල නොපෙන්වූ දෙයක්. මෙය එකම හේතුව බව මම නොකියමි, මම අලුත් දෙයක් පෙන්වමි.
සැල්වදෝර් ඩාලි

1
මෙය වැරදියි: "මෙන්න මෙන්න: මිලි තත්පර 0 ක ප්‍රමාදයකින් setTimeout ලබා ගත නොහැක." ඒ නිසයි. 4ms ප්‍රමාදය setTimeout(fn,0)ප්‍රයෝජනවත් වන්නේ ඇයිද යන්න අදාල නොවේ.
ව්ලැඩිමීර් කෝර්නියා

@ user2407309 එය "අන් අය ප්‍රකාශ කළ හේතු එකතු කිරීම සඳහා පහසුවෙන් වෙනස් කළ හැකිය, එය කළ නොහැක ....". එබැවින් ඔබේම පිළිතුර අළුත් දෙයක් නොකියන්නේ නම් මේ නිසා පහත් කොට සැලකීම හාස්‍යයට කරුණකි. කුඩා සංස්කරණයක් පමණක් ප්‍රමාණවත් වේ.
සැල්වදෝර් ඩාලි

10
සැල්වදෝර් ඩාලි: ඔබ මෙහි ඇති ක්ෂුද්‍ර ගිනි යුද්ධයේ චිත්තවේගීය අංශ නොසලකා හැරියහොත්, @ ව්ලැඩිමීර් කෝර්නියා නිවැරදි බව ඔබ පිළිගත යුතුය. බ්‍රව්සර් 0ms ප්‍රමාදයක් 4ms දක්වා සිතියම් ගත කරන බව සත්‍යයකි, නමුත් එසේ නොවුනත්, ප්‍රති results ල තවමත් එසේමය. මෙහි ඇති රිය පැදවීමේ යාන්ත්‍රණය නම්, ඇමතුම් තොගයට වඩා කේතය පෝලිමට තල්ලු කිරීමයි. මෙම විශිෂ් J JSConf ඉදිරිපත් කිරීම දෙස බලන්න, එය ගැටළුව පැහැදිලි කර ගැනීමට උපකාරී වනු ඇත: youtube.com/watch?v=8aGhZQkoFbQ
hashchange

1
සුදුසුකම් ලත් අවම 4 එම්එස් සඳහා ඔබේ මිල ගණන් ගෝලීය අවම එම්එස් 4 ක් යැයි ඔබ සිතන්නේ මන්දැයි මම ව්‍යාකූල වී සිටිමි. HTML5 පිරිවිතරයෙන් ඔබගේ උපුටා දැක්වීම පෙන්නුම් කරන පරිදි, අවම අගය 4 එම්එස් වන්නේ ඔබ මට්ටම් පහකට වඩා ගැඹුරට setTimeout/ setIntervalවැඩි ගණනක් ඇමතුම් ලබා ගත් විට පමණි ; ඔබ නොමැති නම්, අවම 0 ms (කාල යන්ත්‍ර නොමැති විට). මොසිල්ලාගේ ලියකියවිලි එය නැවත නැවත ආවරණය කිරීම සඳහා පමණක් නොව, කැදැලි අවස්ථා පමණක් ආවරණය කරයි (එබැවින් setInterval0 පරතරය සමඟ කිහිප වතාවක්ම නැවත උපලේඛනගත වනු ඇත, පසුව ඉන් පසුව වැඩි වේලාවක් ප්‍රමාද වනු ඇත), නමුත් setTimeoutඅවම කැදැල්ල සහිත සරල භාවිතයන් වහාම පෝලිම් ගැසීමට අවසර දෙනු ලැබේ.
ෂැඩෝ රේන්ජර්

9

මෙම ඉහළම ශ්‍රේණිගත කළ පිළිතුරු දෙකම වැරදිය. සමගාමී මුදල් ආකෘතිය සහ සිදුවීම් ලූපය පිළිබඳ එම්ඩීඑන් විස්තරය පරීක්ෂා කරන්න , එවිට සිදුවන්නේ කුමක්ද යන්න පැහැදිලි විය යුතුය (එම්ඩීඑන් සම්පත සැබෑ මැණික් වර්ගයකි). හා සරලව භාවිතා setTimeout පොඩි ප්රශ්නයක් "විසඳනවා" අමතරව ඔබගේ කේතය නොසිතූ ගැටලු එකතු කළ හැක.

මොකක්ද ඇත්තටම මෙතන වෙන්නේ මත පදනම් හෝ යමක් "බ්රව්සරය තරමක් සූදානම් තවමත් මෙයට හේතුව, විය නොහැකි විය 'බව නොවේ" එක් එක් මාර්ගය පෝලිමේ පිටුපස එකතු රැඳි සිදුවීමකි. "

මෙම jsfiddle DVK විසින් සපයන සැබවින්ම ප්රශ්නය පෙන්නුම් නොව, ඒ සඳහා ඔහුගේ පැහැදිලි කිරීමක් නිවැරදි නොවේ.

ඔහුගේ කේතයේ සිදුවෙමින් පවතින්නේ ඔහු මුලින්ම සිදුවීම් හසුරුවන්නෙකු බොත්තම clickමත ඇති සිදුවීමට අනුයුක්ත කිරීමයි #do.

ඉන්පසු, ඔබ සැබවින්ම බොත්තම ක්ලික් කළ විට, messageසිදුවීම් හසුරුවන ශ්‍රිතය සඳහන් කරමින් a සාදනු ලැබේ message queue. event loopමෙම පණිවිඩය වෙත ළඟා වූ විට , එය framejsfiddle හි ක්ලික් සිදුවීම් හසුරුවන්නා වෙත ක්‍රියාකාරී ඇමතුම සමඟ, තොගයේ මතයක් නිර්මාණය කරයි .

එය සිත්ගන්නාසුලු තැනක් වන්නේ මෙහිදීය. අපි ජාවාස්ක්‍රිප්ට් අසමමුහුර්ත යැයි සිතීමට පුරුදු වී සිටිමු. මෙම කුඩා කාරණය නොසලකා හැරීමට අපට හැකියාවක් ඇත : ඊළඟ රාමුව ක්‍රියාත්මක කිරීමට පෙර ඕනෑම රාමුවක් සම්පූර්ණයෙන් ක්‍රියාත්මක කළ යුතුය . සහසම්බන්ධයක් නැත, මිනිසුන්.

මෙමගින් කුමක් වෙයිද? එහි අර්ථය වන්නේ පණිවිඩ පෝලිමේ සිට ශ්‍රිතයක් යෙදූ විට, එය ජනනය කරන තොගය හිස් වන තුරු එය පෝලිම් අවහිර කිරීමයි. නැතහොත්, වඩාත් සාමාන්‍යයෙන්, ශ්‍රිතය නැවත පැමිණෙන තෙක් එය අවහිර කරයි. තවද එය DOM විදැහුම්කරණ මෙහෙයුම්, අනුචලනය සහ වොට්නොට් ඇතුළු සියල්ල අවහිර කරයි. ඔබට තහවුරු කිරීමක් අවශ්‍ය නම්, ෆෙඩල් හි දීර් running කාලයක් තිස්සේ ක්‍රියාත්මක වන කාලය වැඩි කිරීමට උත්සාහ කරන්න (උදා: පිටත ලූපය තවත් 10 වතාවක් ධාවනය කරන්න), එය ක්‍රියාත්මක වන විට ඔබට පිටුව අනුචලනය කළ නොහැකි බව ඔබට පෙනෙනු ඇත. එය ප්‍රමාණවත් තරම් දිගු කාලයක් ධාවනය කරන්නේ නම්, ඔබට ක්‍රියාවලිය විනාශ කිරීමට අවශ්‍ය දැයි ඔබගේ බ්‍රව්සරය ඔබෙන් අසනු ඇත, මන්ද එය පිටුව ප්‍රතිචාර නොදක්වන බැවිනි. රාමුව ක්‍රියාත්මක වන අතර සිදුවීම් ලූපය සහ පණිවිඩ පෝලිම එය අවසන් වන තුරු සිරවී ඇත.

පා text යේ මෙම අතුරු ආබාධ යාවත්කාලීන නොවන්නේ ඇයි? ඔබ අතර නිසා ඇති ඔබට හැකි - විශ්ලේෂණයට DOM දී අංගයක් වටිනාකම වෙනස් console.log()වහාම එය වෙනස් පසුව එහි වටිනාකම සහ එය බලන්න කර ඇත (DVK පැහැදිලි නිවැරදි නොවේ ඇයි පෙන්වයි) වෙනස් කර - බ්රව්සරය deplete කිරීමට අඩුක්කුව සඳහා නැවතී ඇත (මෙම onනැවත හැසිරවීම උත්සවය) හා ඒ අනුව එම පණිවිඩය අවසන් කිරීමට, එය අවසානයේ අපගේ විකෘති මෙහෙයුම ප්රතික්රියාවල ලෙස ක්රියාත්මක වීමේදී විසින් එකතු කර ඇති බව එම පණිවිඩය ක්රියාත්මක කිරීමට වටා ලබා ගත හැකි බව, සහ පරිශීලක අතුරු මුහුණත බව විකෘති පිළිබිඹු කිරීම පිණිස .

මෙයට හේතුව අපි ඇත්ත වශයෙන්ම කේතය ක්‍රියාත්මක වන තෙක් බලා සිටීමයි. අපි සාමාන්‍යයෙන් අපගේ සිදුවීම් මත පදනම් වූ අසමමුහුර්ත ජාවාස්ක්‍රිප්ට් සමඟ කරන ආකාරයට "කවුරුහරි මෙය ලබාගෙන ප්‍රති function ල සමඟ මෙම ශ්‍රිතය අමතන්න, ස්තූතියි, දැන් මම ඉමා ආපසු පැමිණීම, දැන් ඕනෑම දෙයක් කරන්න" යනුවෙන් පවසා නැත. අපි ක්ලික් ඉසව් හසුරුවන ශ්‍රිතයක් ඇතුළත් කරන්නෙමු, අපි DOM අංගයක් යාවත්කාලීන කරන්නෙමු, අපි තවත් ශ්‍රිතයක් අමතන්නෙමු, අනෙක් ශ්‍රිතය දීර් time කාලයක් ක්‍රියාත්මක වන අතර පසුව නැවත පැමිණේ, පසුව අපි එකම DOM මූලද්‍රව්‍යය යාවත්කාලීන කර, පසුව ආරම්භක ශ්‍රිතයෙන් ආපසු, effectively ලදායී ලෙස හිස් කරමු තොගය. හා පසුව බ්රව්සරය, ඉතා හොඳින් සමහර අභ්යන්තර කලේ ය "මත-DOM-විකෘති" වර්ගය සිද්ධිය මගින් අප විසින් ජනනය පණිවිඩයක් විය හැකි වන පෝලිමේ ඊළඟ පණිවිඩයට ලබා ගත හැක.

දැනට ක්‍රියාත්මක වන රාමුව අවසන් වන තුරු (ශ්‍රිතය නැවත පැමිණේ) බ්‍රව්සරයේ UI හට UI යාවත්කාලීන කළ නොහැක (හෝ නොකිරීමට තීරණය කරයි). පුද්ගලිකව, මම සිතන්නේ මෙය සීමා කිරීමකට වඩා නිර්මාණයෙන් බවයි.

ඇයි setTimeoutඑහෙනම් වැඩ කරන්නේ? එය එසේ කරන්නේ, එය දිගු කාලීනව ක්‍රියාත්මක වන ඇමතුම එහි රාමුවෙන් effectively ලදායී ලෙස ඉවත් කර, පසුව windowසන්දර්භය තුළ එය ක්‍රියාත්මක කිරීමට උපලේඛනගත කර ඇති නිසා එමඟින් වහාම ආපසු පැමිණ පණිවිඩ පෝලිම් වෙනත් පණිවිඩ සැකසීමට ඉඩ සලසයි. DOM හි පෙළ වෙනස් කිරීමේදී ජාවාස්ක්‍රිප්ට් හි අප විසින් අවුලුවන ලද UI “යාවත්කාලීන” පණිවිඩය දිගුකාලීන ක්‍රියාකාරිත්වය සඳහා පෝලිම්වල ඇති පණිවිඩයට වඩා ඉදිරියෙන් සිටින අතර, එමඟින් අප අවහිර කිරීමට පෙර UI යාවත්කාලීන කිරීම සිදු වේ. දිගු කාලයකට.

අ) දිගුකාලීනව ක්‍රියාත්මක වන සෑම දෙයක්ම ක්‍රියාත්මක වන විට එය තවමත් අවහිර කරන බව සලකන්න. ආ) පණිවිඩ පෝලිමේ යූඅයි යාවත්කාලීනය ඇත්ත වශයෙන්ම ඊට වඩා ඉදිරියෙන් සිටින බවට ඔබට සහතික නැත. මගේ ජූනි 2018 ක්‍රෝම් බ්‍රව්සරයේ, 0ෆෙඩෙල් පෙන්වන ගැටළුව “නිරාකරණය” නොකෙරේ - 10 ක්. මම ඇත්ත වශයෙන්ම මෙයින් තරමක් තදින් සිටිමි, මන්ද යූඅයි යාවත්කාලීන පණිවිඩය ඊට පෙර පෝලිම් ගත යුතු බව මට තර්කානුකූලව පෙනේ, මන්ද එහි ප්‍රේරකය ක්‍රියාත්මක වන්නේ දිගුකාලීනව ක්‍රියාත්මක වන “පසුව” ක්‍රියාත්මක කිරීමට උපලේඛනගත කිරීමට පෙරය. නමුත් සමහර විට V8 එන්ජිම තුළ යම් යම් ප්‍රශස්තිකරණයන් බාධා ඇති විය හැකිය, නැතහොත් සමහර විට මගේ අවබෝධය නොමැති විය හැකිය.

හරි, ඉතින් භාවිතා කිරීමේ ගැටලුව setTimeoutකුමක්ද, මෙම විශේෂිත අවස්ථාව සඳහා වඩා හොඳ විසඳුම කුමක්ද?

පළමුවෙන්ම, setTimeoutවෙනත් ඕනෑම ගැටළුවක් සමනය කිරීමට උත්සාහ කිරීම සඳහා මෙවැනි සිදුවීම් හසුරුවන්නෙකු භාවිතා කිරීමේ ගැටළුව වෙනත් කේත සමඟ පටලවා ගැනීමට ඉඩ ඇත. මෙන්න මගේ කාර්යයෙන් සැබෑ ජීවිත උදාහරණයක්:

සිදුවීම් ලූපය පිළිබඳ වැරදි දැනුමක් ඇති සගයකු, ජාවාස්ක්‍රිප්ට් setTimeout 0එහි විදැහුම්කරණය සඳහා යම් අච්චු විදැහුම්කරණ කේත භාවිතයෙන් "නූල්" කිරීමට උත්සාහ කළේය . ඔහු තවදුරටත් විමසීමට මෙහි නැත, නමුත් සමහර විට ඔහු විදැහුම්කරණ වේගය මැනීම සඳහා ටයිමරයන් ඇතුළත් කර ඇති බව මට සිතිය හැකිය (එය නැවත පැමිණීමේ ක්ෂණික ක්‍රියාකාරිත්වය වනු ඇත) සහ මෙම ප්‍රවේශය භාවිතා කිරීමෙන් එම ශ්‍රිතයෙන් වේගයෙන් ප්‍රතිචාර දැක්විය හැකි බව මට පෙනී ගියේය.

පළමු ගැටළුව පැහැදිලිය; ඔබට ජාවාස්ක්‍රිප්ට් නූල් කළ නොහැක, එබැවින් ඔබ අපැහැදිලි එකතු කරන අතරතුර මෙහි කිසිවක් දිනා නොගනී. දෙවනුව, ඔබ දැන් අච්චුව විදැහුම්කරණය කළ හැකි සිදුවීම් සවන්දෙන්නන්ගේ තොගයෙන් effectively ලදායී ලෙස වෙන් කර ඇති අතර එම අච්චුව විදැහුම් කරනු ඇතැයි අපේක්ෂා කළ හැකි අතර එය එසේ නොවන්නට ඇත. එම ශ්‍රිතයේ සත්‍ය හැසිරීම දැන් නිර්ණායක නොවන අතර, නොදැනුවත්වම - එය ක්‍රියාත්මක වන හෝ එය මත රඳා පවතින ඕනෑම ශ්‍රිතයක්. ඔබට උගත් අනුමාන කළ හැකිය, නමුත් එහි හැසිරීම පිළිබඳව ඔබට නිසි ලෙස කේත කළ නොහැක.

නව සිදුවීම් හසුරුවන්නෙකු එහි තර්කනය මත රඳා පවතින විට එය නිවැරදි කිරීම භාවිතා කිරීම ය setTimeout 0. නමුත්, එය නිවැරදි කිරීමක් නොවේ, එය තේරුම් ගැනීමට අපහසු වන අතර, මේ වගේ කේත නිසා ඇති වන දෝෂ නිරාකරණය කිරීම විනෝදයක් නොවේ. සමහර විට කිසි විටෙකත් කිසිදු ගැටළුවක් නොමැත, තවත් විටෙක එය සංක්ෂිප්තව අසමත් වේ, පසුව නැවතත්, සමහර විට එය ක්‍රියාත්මක වන අතර වරින් වර කැඩී යයි, වේදිකාවේ වර්තමාන ක්‍රියාකාරිත්වය සහ එම අවස්ථාවේ සිදුවීමට සිදුවන වෙනත් දේ මත පදනම්ව. මම පෞද්ගලිකව (එය මෙම නම්න් භාවිතා එරෙහිව උපදෙස් බව කියා ඇත්තේ ඒ නිසාය වේ ඔබ ඇත්තටම ඔබ කරන්නේ කුමක්ද ඇති ප්රතිවිපාක මොකක්ද කියලා නොකරන්නේ නම්, නම්න්, සහ එය බව අප සියලු දෙනා දන්නා යුතුය).

නමුත් ඒ වෙනුවට අපට කුමක් කළ හැකිද? හොඳයි, යොමු කරන ලද එම්ඩීඑන් ලිපියේ දැක්වෙන පරිදි, එක්කෝ වැඩ බහු පණිවුඩවලට බෙදන්න (ඔබට හැකි නම්) එවිට පෝලිම් ගැසී ඇති අනෙකුත් පණිවිඩ ඔබේ වැඩ සමඟ අන්තර් සම්බන්ධ වී එය ක්‍රියාත්මක වන විට ක්‍රියාත්මක කළ හැකිය, නැතහොත් ක්‍රියාත්මක විය හැකි වෙබ් සේවකයෙකු භාවිතා කරන්න. ඔබේ පිටුව සමඟ සමපාත වන අතර එහි ගණනය කිරීම් සමඟ ප්‍රති results ල ලබා දෙන්න.

ඔහ්, ඔබ සිතන්නේ නම්, "හොඳයි, එය අසමමුහුර්ත කිරීම සඳහා දිගුකාලීන ක්‍රියාකාරිත්වයට ඇමතුමක් ලබා දිය නොහැකිද?", එසේ නොවේ. ඇමතුම් ආපසු එය අසමමුහුර්ත නොකරයි, ඔබේ ඇමතුම පැහැදිලිව ඇමතීමට පෙර එයට දිගුකාලීන කේතය ක්‍රියාත්මක කිරීමට සිදුවනු ඇත.


1
මෙම සම්පූර්ණ පිටුවේ ඇති එකම වලංගු හා සම්පූර්ණ ප්‍රකාශය ලෙස
පෙනේ

8

එය කාල සීමාවක් පසුකරමින් පවතින බැවින්, එය ක්‍රියාත්මක කිරීමේ ප්‍රවාහයෙන් ලබා දුන් 0කේතය ඉවත් කිරීම සඳහා යැයි මම සිතමි setTimeout. එබැවින් එය යම් කාලයක් ගතවිය හැකි ශ්‍රිතයක් නම්, එය පසු කේතය ක්‍රියාත්මක කිරීමෙන් වලක්වනු නොලැබේ.


FYI: මෙම පිළිතුර stackoverflow.com/questions/4574940/…
Shog9

3

මෙය කරන අනෙක් දෙය නම් ශ්‍රිත ආයාචනය තොගයේ පහළට තල්ලු කිරීම, ඔබ පුනරාවර්තනයක් ශ්‍රිතයක් අමතන්නේ නම් තොග පිටාර ගැලීම වළක්වයි. මෙය whileලූපයක බලපෑමක් ඇති නමුත් ජාවාස්ක්‍රිප්ට් එන්ජිමට වෙනත් අසමමුහුර්ත ටයිමරයන් ගිනි තැබීමට ඉඩ දෙයි.


මේ සඳහා පහත් කරන්න push the function invocation to the bottom of the stack. දේ stackඔබ ගැන කතා කරන්නේ අප්රකට වේ. වැදගත්ම දෙය නම් setTimeoutමෙම විනෝදය, මෙම ලූප චක්‍රයේ අවසානය හෝ ඊළඟ ලූප චක්‍රයේ ආරම්භය හරියටම එකතු කරන ස්ථානයයි .
හරිත

1

SetTimeout ඇමතීමෙන් ඔබ පරිශීලකයා කරන ඕනෑම දෙයකට ප්‍රතික්‍රියා කිරීමට පිටුවට කාලය ලබා දෙයි. පිටු පැටවීමේදී ක්‍රියාත්මක වන කාර්යයන් සඳහා මෙය විශේෂයෙන් උපකාරී වේ.


1

SetTimeout ප්‍රයෝජනවත් වන තවත් අවස්ථා:

බ්‍රව්සරය 'කැටි කිරීම' හෝ "පිටුවේ ස්ක්‍රිප්ට් කාර්යබහුලයි" යැයි නොකියන පරිදි දිගුකාලීන ලූපයක් හෝ ගණනය කිරීමක් කුඩා කොටස් වලට කැඩීමට ඔබට අවශ්‍යය.

ක්ලික් කිරීමේදී පෝරමය ඉදිරිපත් කිරීමේ බොත්තමක් අක්‍රිය කිරීමට ඔබට අවශ්‍යය, නමුත් ඔබ ඔන්ක්ලික් හසුරුවෙහි ඇති බොත්තම අක්‍රීය කළහොත් ආකෘති පත්‍රය ඉදිරිපත් නොකෙරේ. setTimeout ශුන්‍ය වේලාවක් සමඟ උපක්‍රමය සිදු කරයි, සිදුවීම අවසන් වීමට ඉඩ සලසයි, පෝරමය ඉදිරිපත් කිරීම ආරම්භ කරයි, එවිට ඔබගේ බොත්තම අක්‍රිය කළ හැකිය.


2
අක්‍රීය කිරීම සිදුවීම ඉදිරිපත් කිරීමේදී වඩා හොඳ වනු ඇත; එය වේගවත් වන අතර ඔබට ඉදිරිපත් කිරීම නැවැත්විය හැකි බැවින් ආකෘති පත්‍රය තාක්‍ෂණිකව ඉදිරිපත් කිරීමට පෙර ඇමතීමට සහතික වේ.
ක්‍රිස්

ඉතා ඇත්ත. මූලාකෘතිකරණය සඳහා ඔන්ක්ලික් අක්‍රීය කිරීම පහසු යැයි මම සිතමි, මන්ද ඔබට බොත්තම මත onclick = "this.disabled = true" ටයිප් කළ හැකි අතර ඉදිරිපත් කිරීම අක්‍රීය කිරීමට තරමක් වැඩි වැඩක් අවශ්‍ය වේ.
fabspro

1

ක්‍රියාත්මක කිරීමේ ලූප සහ වෙනත් කේතයක් සම්පූර්ණ වීමට පෙර DOM විදැහුම්කරණය පිළිබඳ පිළිතුරු නිවැරදි ය. ජාවාස්ක්‍රිප්ට් හි ශුන්‍ය දෙවන කාලරාමුව කේතය ව්‍යාජ බහු-ත්‍රෙඩ් කිරීමට එය උපකාරී වේ.

ජාවාස්ක්‍රිප්ට් හි හරස් බ්‍රව්සරයක් / හරස් වේදිකාවක් සඳහා හොඳම අගය 0 (බිංදුව) වෙනුවට මිලි තත්පර 20 ක් පමණ වන බව මට එක් කිරීමට අවශ්‍යයි, මන්ද බොහෝ ජංගම බ්‍රව්සරවලට ඔරලෝසු සීමාවන් නිසා මිලි තත්පර 20 ට වඩා අඩු කාලරාමු ලියාපදිංචි කළ නොහැක. AMD චිප්ස් මත.

එසේම, DOM හැසිරවීමට සම්බන්ධ නොවන දිගුකාලීන ක්‍රියාදාමයන් දැන් වෙබ් සේවකයින් වෙත යැවිය යුතුය, මන්ද ඔවුන් ජාවාස්ක්‍රිප්ට් සත්‍ය ලෙසම ක්‍රියාත්මක කරන බැවිනි.


2
ඔබගේ පිළිතුර ගැන මට යම් සැකයක් ඇත, නමුත් එය ඉහළට ඔසවා තැබුවේ එය බ්‍රව්සර් ප්‍රමිතීන් පිළිබඳව අමතර පර්යේෂණ කිරීමට මට බල කළ බැවිනි. ප්රමිතීන් පර්යේෂණ කරන විට, මම, මම හැම විටම කොහේ යන්න MDN: developer.mozilla.org/en-US/docs/Web/API/window.setTimeout HTML5 පිරිවිතර 4ms පවසයි. ජංගම චිප වල ඔරලෝසු සීමාවන් ගැන එය කිසිවක් නොකියයි. ඔබේ ප්‍රකාශයන් උපස්ථ කිරීම සඳහා තොරතුරු ප්‍රභවයක් සොයා ගැනීමට අපහසු වීම. ගූගල් විසින් ඩාර්ට් භාෂාව සොයා ගත්තේ ටයිමර් වස්තුවකට පක්ෂව සෙට් ටයිමවුට් ඉවත් කරමිනි.
ජෝන් සැබ්‍රොස්කි

8
(...) ඔරලෝසු සීමාවන් නිසා බොහෝ ජංගම බ්‍රව්සර් වලට මිලි තත්පර 20 ට වඩා අඩු කාලරාමු ලියාපදිංචි කළ නොහැකි නිසා (...) සෑම වේදිකාවක්ම එහි ඔරලෝසුව නිසා කාල සීමාවන් ඇති අතර ඊළඟට හරියටම තත්පර 0 කට පසුව ක්‍රියාත්මක කිරීමට කිසිදු වේදිකාවක් සමත් නොවේ . වත්මන් එකක්. 0ms කල් ඉකුත්වීම හැකි ඉක්මනින් ශ්‍රිතයක් ක්‍රියාත්මක කරන ලෙස ඉල්ලා සිටින අතර නිශ්චිත වේදිකාවේ කාල සීමාවන් මෙහි අර්ථය කිසිදු ආකාරයකින් වෙනස් නොකරයි.
පියොටර් ඩොබ්‍රොගොස්ට්

1

setTimout on 0 ද කල් දැමූ පොරොන්දුවක් සැකසීමේ රටාවට ඉතා ප්‍රයෝජනවත් වේ, එය ඔබට වහාම ආපසු යාමට අවශ්‍යය:

myObject.prototype.myMethodDeferred = function() {
    var deferredObject = $.Deferred();
    var that = this;  // Because setTimeout won't work right with this
    setTimeout(function() { 
        return myMethodActualWork.call(that, deferredObject);
    }, 0);
    return deferredObject.promise();
}

1

ගැටළුව වූයේ ඔබ නොපවතින මූලද්‍රව්‍යයක් මත ජාවාස්ක්‍රිප්ට් මෙහෙයුමක් කිරීමට උත්සාහ කිරීමයි. මූලද්රව්යය තවමත් පටවා නොමැති setTimeout()අතර මූලද්රව්යයක් පහත දැක්වෙන ආකාරයෙන් පැටවීමට වැඩි කාලයක් ලබා දෙයි:

  1. setTimeout()එම නිසා සිදුවීම සමමුහුර්ත වීමට හේතු වන අතර එමඟින් සියලු සමමුහුර්ත කේතයෙන් පසුව ක්‍රියාත්මක වන අතර එමඟින් ඔබේ මූලද්‍රව්‍යය පැටවීමට වැඩි කාලයක් ලබා දේ. දී callback වැනි අසමමිතික callbacks setTimeout()තුළ තැන්පත් කර ඇත අවස්ථාවට පෝලිමේ හා විසින් අඩුක්කුව දමා අවස්ථාවට පුඩුවක් සමමුහුර්ත කේත අඩුක්කුව හිස් පසු.
  2. ශ්‍රිතයේ දෙවන තර්කයක් ලෙස ms සඳහා 0 අගය setTimeout()බොහෝ විට තරමක් වැඩි වේ (බ්‍රව්සරය අනුව 4-10ms). setTimeout()ඇමතුම් ආපසු ලබා ගැනීම සඳහා අවශ්‍ය තරමක් වැඩි කාලයක් සිදුවන්නේ සිදුවීම් ලූපයේ 'කිනිතුල්ලන්' ප්‍රමාණය (ටික් එකක් තොගයක් හිස්ව තිබේ නම් එය නැවත ගොඩට තල්ලු කරයි). ක්‍රියාකාරීත්වය සහ බැටරි ආයු කාලය නිසා සිදුවීම් ලූපයේ කිනිතුල්ලන් ප්‍රමාණය තත්පරයට 1000 වතාවකට වඩා අඩු ප්‍රමාණයකට සීමා වේ .

-1

ජාවාස්ක්‍රිප්ට් යනු තනි නූල් සහිත යෙදුමක් වන අතර එමඟින් සමගාමීව ක්‍රියා කිරීමට ඉඩ නොදෙන අතර එමඟින් මෙම සිදුවීම් ලූප භාවිතා කරනු ලැබේ. ඉතින් හරියටම සෙට් ටයිම out ට් (fn, 0) කරන්නේ එය ඔබගේ ඇමතුම් තොගය හිස් වූ විට ක්‍රියාත්මක වන කාර්ය ගවේෂණය සඳහා යොමු කිරීමයි. මෙම පැහැදිලි කිරීම ඉතා නීරස බව මම දනිමි, එබැවින් මෙම වීඩියෝව හරහා යාමට මම ඔබට නිර්දේශ කරමි, බ්‍රව්සරයේ කබාය යටතේ දේවල් ක්‍රියාත්මක වන ආකාරය මෙය ඔබට උපකාරී වනු ඇත. මෙම වීඩියෝව බලන්න: - https://www.youtube.com/watch?time_continue=392&v=8aGhZQkoFbQ

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.