මෙම ඉහළම ශ්රේණිගත කළ පිළිතුරු දෙකම වැරදිය. සමගාමී මුදල් ආකෘතිය සහ සිදුවීම් ලූපය පිළිබඳ එම්ඩීඑන් විස්තරය පරීක්ෂා කරන්න , එවිට සිදුවන්නේ කුමක්ද යන්න පැහැදිලි විය යුතුය (එම්ඩීඑන් සම්පත සැබෑ මැණික් වර්ගයකි). හා සරලව භාවිතා setTimeout
පොඩි ප්රශ්නයක් "විසඳනවා" අමතරව ඔබගේ කේතය නොසිතූ ගැටලු එකතු කළ හැක.
මොකක්ද ඇත්තටම මෙතන වෙන්නේ මත පදනම් හෝ යමක් "බ්රව්සරය තරමක් සූදානම් තවමත් මෙයට හේතුව, විය නොහැකි විය 'බව නොවේ" එක් එක් මාර්ගය පෝලිමේ පිටුපස එකතු රැඳි සිදුවීමකි. "
මෙම jsfiddle DVK විසින් සපයන සැබවින්ම ප්රශ්නය පෙන්නුම් නොව, ඒ සඳහා ඔහුගේ පැහැදිලි කිරීමක් නිවැරදි නොවේ.
ඔහුගේ කේතයේ සිදුවෙමින් පවතින්නේ ඔහු මුලින්ම සිදුවීම් හසුරුවන්නෙකු බොත්තම click
මත ඇති සිදුවීමට අනුයුක්ත කිරීමයි #do
.
ඉන්පසු, ඔබ සැබවින්ම බොත්තම ක්ලික් කළ විට, message
සිදුවීම් හසුරුවන ශ්රිතය සඳහන් කරමින් a සාදනු ලැබේ message queue
. event loop
මෙම පණිවිඩය වෙත ළඟා වූ විට , එය frame
jsfiddle හි ක්ලික් සිදුවීම් හසුරුවන්නා වෙත ක්රියාකාරී ඇමතුම සමඟ, තොගයේ මතයක් නිර්මාණය කරයි .
එය සිත්ගන්නාසුලු තැනක් වන්නේ මෙහිදීය. අපි ජාවාස්ක්රිප්ට් අසමමුහුර්ත යැයි සිතීමට පුරුදු වී සිටිමු. මෙම කුඩා කාරණය නොසලකා හැරීමට අපට හැකියාවක් ඇත : ඊළඟ රාමුව ක්රියාත්මක කිරීමට පෙර ඕනෑම රාමුවක් සම්පූර්ණයෙන් ක්රියාත්මක කළ යුතුය . සහසම්බන්ධයක් නැත, මිනිසුන්.
මෙමගින් කුමක් වෙයිද? එහි අර්ථය වන්නේ පණිවිඩ පෝලිමේ සිට ශ්රිතයක් යෙදූ විට, එය ජනනය කරන තොගය හිස් වන තුරු එය පෝලිම් අවහිර කිරීමයි. නැතහොත්, වඩාත් සාමාන්යයෙන්, ශ්රිතය නැවත පැමිණෙන තෙක් එය අවහිර කරයි. තවද එය 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 ල ලබා දෙන්න.
ඔහ්, ඔබ සිතන්නේ නම්, "හොඳයි, එය අසමමුහුර්ත කිරීම සඳහා දිගුකාලීන ක්රියාකාරිත්වයට ඇමතුමක් ලබා දිය නොහැකිද?", එසේ නොවේ. ඇමතුම් ආපසු එය අසමමුහුර්ත නොකරයි, ඔබේ ඇමතුම පැහැදිලිව ඇමතීමට පෙර එයට දිගුකාලීන කේතය ක්රියාත්මක කිරීමට සිදුවනු ඇත.