ශ්‍රිතයක් තුළ මා එය වෙනස් කළ පසු මගේ විචල්‍යය වෙනස් නොවන්නේ ඇයි? - අසමමුහුර්ත කේත යොමුව


725

පහත දැක්වෙන උදාහරණ අනුව, outerScopeVarසෑම අවස්ථාවකම නිර්වචනය කර ඇත්තේ ඇයි?

var outerScopeVar;

var img = document.createElement('img');
img.onload = function() {
    outerScopeVar = this.width;
};
img.src = 'lolcat.png';
alert(outerScopeVar);

var outerScopeVar;
setTimeout(function() {
    outerScopeVar = 'Hello Asynchronous World!';
}, 0);
alert(outerScopeVar);

// Example using some jQuery
var outerScopeVar;
$.post('loldog', function(response) {
    outerScopeVar = response;
});
alert(outerScopeVar);

// Node.js example
var outerScopeVar;
fs.readFile('./catdog.html', function(err, data) {
    outerScopeVar = data;
});
console.log(outerScopeVar);

// with promises
var outerScopeVar;
myPromise.then(function (response) {
    outerScopeVar = response;
});
console.log(outerScopeVar);

// geolocation API
var outerScopeVar;
navigator.geolocation.getCurrentPosition(function (pos) {
    outerScopeVar = pos;
});
console.log(outerScopeVar);

undefinedමෙම සියලු උදාහරණ වලින් එය ප්‍රතිදානය කරන්නේ ඇයි ? මට වැඩ කිරීමට අවශ්‍ය නැත, මෙය සිදුවන්නේ ඇයිදැයි දැන ගැනීමට මට අවශ්‍යය .


සටහන: මෙය ජාවාස්ක්‍රිප්ට් අසමමුහුර්තතාව සඳහා කැනොනිකල් ප්‍රශ්නයකි . මෙම ප්‍රශ්නය වැඩිදියුණු කිරීමට සහ ප්‍රජාවට හඳුනාගත හැකි වඩාත් සරල උදාහරණ එක් කිරීමට නිදහස් වන්න.



Uk ඩුකෙලිං ස්තූතියි, මම එම සබැඳිය සමඟ අදහස් දැක්වූ බව මට හොඳටම විශ්වාසයි. එසේම, ඔබගේ සංස්කරණය සම්බන්ධයෙන්: මාතෘකාව තුළ “කැනොනිකල්” සහ “අසමමුහුර්තතාව” තිබීම මෙම ප්‍රශ්නය සෙවීමේදී තවත් ප්‍රශ්නයක් ඩුප් ලෙස සලකුණු කිරීමට උපකාරී වේ. ඇත්ත වශයෙන්ම, අසමමුහුර්ත පැහැදිලි කිරීම් සොයන විට ගූගල් වෙතින් මෙම ප්‍රශ්නය සොයා ගැනීමටද එය උපකාරී වේ.
ෆැබ්රේෂියෝ මැට්

5
තව ටිකක් සිතීම, "කැනොනිකල් අසමමුහුර්ත මාතෘකාව" මාතෘකාව මත තරමක් බරයි, "අසමමුහුර්ත කේත යොමු කිරීම" සරල හා වඩා වෛෂයික ය. බොහෝ අය "අසමමුහුර්තතාව" වෙනුවට "අසමමුහුර්ත" සොයන බව මම විශ්වාස කරමි.
ෆැබ්රේෂියෝ මැට්

2
සමහර අය ශ්‍රිත ඇමතුමට පෙර ඔවුන්ගේ විචල්‍යය ආරම්භ කරයි. කෙසේ හෝ එය නියෝජනය කරන මාතෘකාව වෙනස් කිරීම ගැන කුමක් කිව හැකිද? " ශ්‍රිතයක් තුළ මා එය වෙනස් කළ පසු මගේ විචල්‍යය වෙනස් නොවන්නේ ඇයි ?" ?
ෆීලික්ස් ක්ලින්ග්

ඔබ ඉහත සඳහන් කළ සියලුම කේත උදාහරණ වල, "අනතුරු ඇඟවීම (පිටත දර්ශනය);" දැන් ක්‍රියාත්මක කරයි, නමුත් "පිටත දර්ශකය" සඳහා අගය පැවරීම LATER (අසමමුහුර්තව) සිදු වේ.
refactor

Answers:


571

එක් වචනයකට පිළිතුර: අසමමුහුර්තතාව .

පෙරවදන

මෙම මාතෘකාව අඩුම තරමින් දහස් වාරයක්වත් නැවත නැවතත් කර ඇත. එබැවින්, පළමුවෙන්ම මම අතිශයින්ම ප්‍රයෝජනවත් සම්පත් කිහිපයක් පෙන්වා දීමට කැමැත්තෙමි:


අත ළඟ ඇති ප්‍රශ්නයට පිළිතුර

පළමුව පොදු හැසිරීම සොයා ගනිමු. සියලුම උදාහරණ වලදී, ශ්‍රිතයක්outerScopeVar තුළ වෙනස් කර ඇත . එම ශ්‍රිතය පැහැදිලිවම ක්ෂණිකව ක්‍රියාත්මක නොවේ, එය පවරනු ලැබේ හෝ තර්කයක් ලෙස සම්මත වේ. බව අපි නම්වන callback .

දැන් ප්රශ්නය වන්නේ, එම ඇමතුම නැවත කැඳවන්නේ කවදාද යන්නයි.

එය නඩුව මත රඳා පවතී. පොදු හැසිරීම් කිහිපයක් නැවත සොයා ගැනීමට උත්සාහ කරමු:

  • img.onloadරූපය සාර්ථකව පටවා ඇති විට (සහ තිබේ නම්) අනාගතයේදී එය හැඳින්විය හැක .
  • setTimeoutප්‍රමාදය කල් ඉකුත්වී කල් ඉකුත්වීම අවලංගු නොකිරීමෙන් පසුව අනාගතයේ යම් වේලාවක කැඳවනු ලැබේ clearTimeout. සටහන: 0ප්‍රමාදයක් ලෙස භාවිතා කරන විටදී පවා , සියලුම බ්‍රව්සර්වල අවම කල් ඉකුත් වීමේ ප්‍රමාද තොප්පිය ඇත (HTML5 පිරිවිතරයේ 4ms ලෙස දක්වා ඇත).
  • අජැක්ස් ඉල්ලීම සාර්ථකව අවසන් වූ විට (සහ නම්) jQuery $.postහි ඇමතුම අනාගතයේදී යම් වේලාවක කැඳවනු ලැබේ .
  • අනාගතයේදී ගොනුව සාර්ථකව කියවා හෝ දෝෂයක් ඇති වූ විට Node.js fs.readFileලෙස හැඳින්විය හැක .

සෑම අවස්ථාවකම, අපට නැවත ඇමතුමක් ඇති අතර එය අනාගතයේ යම් වේලාවක ක්‍රියාත්මක විය හැකිය . මෙම "අනාගතයේ යම් වේලාවක" අපි අසමමුහුර්ත ප්‍රවාහයක් ලෙස හඳුන්වමු .

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

වඩාත් නිශ්චිතවම, ජේඑස් එන්ජිම අක්‍රියව පවතින විට - (අ) සමමුහුර්ත කේතයක් ක්‍රියාත්මක නොකිරීම - එය අසමමුහුර්ත ඇමතුම් ලබා ගැනීමට හේතු වූ සිදුවීම් සඳහා ඡන්දය ප්‍රකාශ කරනු ඇත (උදා: කල් ඉකුත් වූ කල් ඉකුත්වීම, ජාල ප්‍රතිචාර ලැබීම) ඒවා එකින් එක ක්‍රියාත්මක කරයි. මෙය සිදුවීම් ලූප් ලෙස සැලකේ .

එනම්, අතින් සාදන ලද රතු හැඩයන්හි උද්දීපනය කර ඇති අසමමුහුර්ත කේතය ක්‍රියාත්මක කළ හැක්කේ අදාළ කේත කොටස්වල ඉතිරිව ඇති සියලුම සමමුහුර්ත කේතය ක්‍රියාත්මක කිරීමෙන් පසුව පමණි:

අසින්ක් කේතය ඉස්මතු කර ඇත

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

එය ඇත්තෙන්ම සරලයි. අසමමුහුර්ත ශ්‍රිතය ක්‍රියාත්මක කිරීම මත රඳා පවතින තර්කනය මෙම අසමමුහුර්ත ශ්‍රිතය ඇතුළත සිට ආරම්භ කළ යුතුය. නිදසුනක් ලෙස, ඇමතුම් ආපසු ගැනීමේ ශ්‍රිතය තුළ alerts සහ console.logs චලනය කිරීමෙන් අපේක්ෂිත ප්‍රති result ලය ලැබෙනු ඇත, මන්ද එම අවස්ථාවෙහිදී ප්‍රති result ලය ලබා ගත හැකිය.

ඔබේම ඇමතුම් ආපසු ගැනීමේ තර්කනය ක්‍රියාත්මක කිරීම

බොහෝ විට ඔබ අසමමුහුර්ත ශ්‍රිතයක ප්‍රති result ලය සමඟ තවත් බොහෝ දේ කිරීමට හෝ අසමමුහුර්ත ශ්‍රිතය හැඳින්වූ ස්ථානය අනුව ප්‍රති result ලය සමඟ විවිධ දේ කිරීමට අවශ්‍ය වේ. අපි ටිකක් සංකීර්ණ උදාහරණයකට මුහුණ දෙමු:

var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);

function helloCatAsync() {
    setTimeout(function() {
        outerScopeVar = 'Nya';
    }, Math.random() * 2000);
}

සටහන: මම භාවිතා කරනවා setTimeoutඇති Generic බලපත්රය යටතේ අවසර ලබා ඇත අසමමිතික ශ්රිතයක් ලෙස අහඹු ප්රමාද සමග, එම උදාහරණයක් Ajax කිරීමට, අදාළ readFile, onloadසහ වෙනත් ඕනෑම අසමමිතික ප්රවාහය.

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

අපේම ඇමතුම් ලබා ගැනීමේ ක්‍රමයක් ක්‍රියාත්මක කිරීම සමඟ එය විසඳා ගනිමු. පළමුවෙන්ම, outerScopeVarමෙම නඩුවේ සම්පූර්ණයෙන්ම නිෂ් less ල වන එම කැත ඉවත් කරමු . එවිට අපි ශ්‍රිත තර්කයක් පිළිගන්නා පරාමිතියක් එකතු කරමු. අසමමුහුර්ත මෙහෙයුම අවසන් වූ විට, අපි මෙම ඇමතුම ප්‍රති call ලය පසුකරමින් අමතන්නෙමු. ක්‍රියාත්මක කිරීම (කරුණාකර අදහස් පිළිවෙලට කියවන්න):

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    alert(result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    // 3. Start async operation:
    setTimeout(function() {
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

ඉහත උදාහරණයේ කේත ස්නිපටය:

// 1. Call helloCatAsync passing a callback function,
//    which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
    // 5. Received the result from the async function,
    //    now do whatever you want with it:
    console.log("5. result is: ", result);
});

// 2. The "callback" parameter is a reference to the function which
//    was passed as argument from the helloCatAsync call
function helloCatAsync(callback) {
    console.log("2. callback here is the function passed as argument above...")
    // 3. Start async operation:
    setTimeout(function() {
    console.log("3. start async operation...")
    console.log("4. finished async operation, calling the callback, passing the result...")
        // 4. Finished async operation,
        //    call the callback passing the result as argument
        callback('Nya');
    }, Math.random() * 2000);
}

බොහෝ විට සැබෑ භාවිත අවස්ථා වලදී, DOM API සහ බොහෝ පුස්තකාල දැනටමත් ඇමතුම් ලබා ගැනීමේ ක්‍රියාකාරිත්වය සපයයි ( helloCatAsyncමෙම නිරූපණ උදාහරණයේ ක්‍රියාත්මක කිරීම). ඔබට අවශ්‍ය වන්නේ ඇමතුම් ලබා ගැනීමේ ශ්‍රිතය පසු කර එය සමමුහුර්ත ප්‍රවාහයෙන් ක්‍රියාත්මක වන බව තේරුම් ගෙන ඒ සඳහා ඉඩ සැලසෙන පරිදි ඔබේ කේතය ප්‍රතිව්‍යුහගත කිරීමයි.

returnසමමුහුර්ත කේතය දැනටමත් ක්‍රියාත්මක වී බොහෝ කලකට පසු අසමමුහුර්ත ඇමතුම් ආපසු ලබා දෙන බැවින්, අසමමුහුර්ත ස්වභාවය නිසා, අසමමුහුර්ත ප්‍රවාහයක සිට නැවත ඇමතුම අර්ථ දක්වා ඇති සමමුහුර්ත ප්‍රවාහයට අගයක් ලබා ගත නොහැකි බව ඔබ දකිනු ඇත .

returnඅසමමුහුර්ත ඇමතුමකින් වටිනාකමක් ලබා ගැනීම වෙනුවට , ඔබට ඇමතුම් ලබා ගැනීමේ රටාව භාවිතා කිරීමට සිදුවේ, හෝ ... පොරොන්දු.

පොරොන්දු

වැනිලා ජේඑස් සමඟ ඇමතුම් ආපසු නිරයේ තබා ගැනීමට ක්‍රම තිබුණත් , පොරොන්දු ජනප්‍රිය වෙමින් පවතින අතර වර්තමානයේ එය ES6 හි ප්‍රමිතිගත වෙමින් පවතී ( පොරොන්දුව - MDN බලන්න ).

පොරොන්දු (හෝ අනාගත) අසමමුහුර්ත කේතය කියවීම වඩාත් රේඛීය හා ප්‍රසන්න ලෙස සපයන නමුත් ඒවායේ සමස්ත ක්‍රියාකාරිත්වය පැහැදිලි කිරීම මෙම ප්‍රශ්නයේ විෂය පථයෙන් බැහැර ය. ඒ වෙනුවට, මම මෙම විශිෂ්ට සම්පත් උනන්දුවක් දක්වන අයට තබමි:


ජාවාස්ක්‍රිප්ට් අසමමුහුර්තතාව පිළිබඳ වැඩි කියවීමේ තොරතුරු


සටහන: මම මෙම පිළිතුර ප්‍රජා විකී ලෙස සලකුණු කර ඇත්තෙමි, එබැවින් අවම වශයෙන් කීර්තිනාමය 100 ක් ඇති ඕනෑම කෙනෙකුට එය සංස්කරණය කර වැඩි දියුණු කළ හැකිය! කරුණාකර මෙම පිළිතුර වැඩිදියුණු කිරීමට නිදහස් වන්න, නැතහොත් ඔබට අවශ්‍ය නම් සම්පූර්ණයෙන්ම නව පිළිතුරක් ඉදිරිපත් කරන්න.

අජැක්ස් හා සම්බන්ධ නොවන අසමමුහුර්ත ගැටළු වලට පිළිතුරු සැපයීම සඳහා මෙම ප්‍රශ්නය කැනොනිකල් මාතෘකාවක් බවට පත් කිරීමට මට අවශ්‍යය (ඒ සඳහා අජැක්ස් ඇමතුමකින් ප්‍රතිචාරය ලබා දෙන්නේ කෙසේද? ඒ සඳහා), එබැවින් මෙම මාතෘකාවට හැකි තරම් හොඳ සහ ප්‍රයෝජනවත් වීමට ඔබේ උදව් අවශ්‍ය වේ !


1
ඔබගේ අවසාන උදාහරණයේ දී, ඔබ නිර්නාමික ශ්‍රිත භාවිතා කිරීමට නිශ්චිත හේතුවක් තිබේද? නැතහොත් නම් කරන ලද ශ්‍රිත භාවිතා කිරීමෙන් එය එසේම වේද?
JDelage

1
කේත උදාහරණ ටිකක් අමුතුයි, ඔබ එය ඇමතීමෙන් පසුව ශ්‍රිතය ප්‍රකාශ කරන විට. ක්‍රියා කරන්නේ ඇත්ත වශයෙන්ම එසවීම නිසා, නමුත් එය චේතනාන්විතද?
බර්ගි

2
එය අවහිරයක් ද? ෆීලික්ස් ක්ලින්ග් ඔබේ පිළිතුරට යොමු වන අතර ඔබ යොමු කරන්නේ ෆෙලික්ස් පිළිතුරටයි
මහී

1
රතු කවයේ කේතය අසමසම බව ඔබ තේරුම් ගත යුතුය, මන්ද එය ක්‍රියාත්මක වන්නේ NATIVE අසින්ක් ජාවාස්ක්‍රිප්ට් කාර්යයන් මගිනි. මෙය ඔබගේ ජාවාස්ක්‍රිප්ට් එන්ජිමේ ලක්ෂණයකි - එය Node.js හෝ බ්‍රව්සරයක් වේවා. එය අසමසම වන්නේ එය කළු පෙට්ටියක් (සී යනාදිය තුළ ක්‍රියාත්මක කර ඇති) ශ්‍රිතයකට “ඇමතුමක්” ලෙස ලබා දෙන බැවිනි. අසරණ සංවර්ධකයාට ඔවුන් අසමසමයි ... මොකද. ඔබට ඔබේම අසින්ක් ශ්‍රිතයක් ලිවීමට අවශ්‍ය නම් එය සෙට් ටයිමවුට් (myfunc, 0) වෙත යැවීමෙන් එය හැක් කළ යුතුය. ඔබ එය කළ යුතුද? තවත් විවාදයක් .... බොහෝ විට නැත.
ෂෝන් ඇන්ඩර්සන්

Ab ෆැබ්රිෂියෝ මම "> = 4ms ක්ලැම්ප්" යන්න නිර්වචනය කර ඇති නමුත් එය සොයාගත නොහැකි විය - එම්ඩීඑන් - සංවර්ධක / වෙබ් / ඒපීඅයි /… - HTML පිරිවිතරයේ දකුණු කොටසට යමෙකුට සබැඳියක් තිබේද?
සෙබී

154

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


ප්‍රතිසමයක් ...

ඊයේ, මම කරමින් සිටි කාර්යයට සගයකුගෙන් යම් තොරතුරු අවශ්‍ය විය. මම ඔහුව ඔසවා තැබුවෙමි. සංවාදය ගිය ආකාරය මෙන්න:

මට : හායි බොබ්, මම හිතන්නේ අපි දැන සිටිය යුතු foo 'ඈ ද බාර් ඈ පසුගිය සතියේ. ජිම්ට ඒ පිළිබඳ වාර්තාවක් අවශ්‍ය වන අතර ඒ පිළිබඳ විස්තර දන්නේ ඔබ පමණි.

බොබ් : ෂුවර් දෙයක්, නමුත් මට විනාඩි 30 ක් පමණ ගත වේවිද?

මම : ඒක නියමයි බොබ්. ඔබට තොරතුරු ලැබුණු විට මට නැවත මුද්දක් දෙන්න!

මේ අවස්ථාවේදී, මම දුරකථනය එල්ලා තැබුවෙමි. මගේ වාර්තාව සම්පුර්ණ කිරීම සඳහා මට බොබ්ගෙන් තොරතුරු අවශ්‍ය වූ හෙයින්, මම වාර්තාව අතහැර කෝපි කෝප්පයක් ගැනීමට ගියෙමි, පසුව මම ඊමේල් කිහිපයක් අල්ලා ගතිමි. මිනිත්තු 40 කට පසු (බොබ් මන්දගාමී), බොබ් නැවත අමතා මට අවශ්‍ය තොරතුරු ලබා දුන්නේය. මේ අවස්ථාවේ දී, මට අවශ්‍ය සියලු තොරතුරු මා සතුව තිබූ බැවින්, මගේ වාර්තාව සමඟ මගේ වැඩ කටයුතු නැවත ආරම්භ කළෙමි.


ඒ වෙනුවට සංවාදය මේ ආකාරයට සිදුවී ඇත්දැයි සිතා බලන්න;

මට : හායි බොබ්, මම හිතන්නේ අපි දැන සිටිය යුතු foo 'ඈ ද බාර් ඈ පසුගිය සතියේ. ජිම්ට අවශ්‍ය වන්නේ ඒ පිළිබඳ වාර්තාවක් වන අතර ඒ පිළිබඳ විස්තර දන්නේ ඔබ පමණයි.

බොබ් : ෂුවර් දෙයක්, නමුත් මට විනාඩි 30 ක් පමණ ගත වේවිද?

මම : ඒක නියමයි බොබ්. මම බලා ඉන්නම්.

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


මෙය අසමමුහුර්ත එදිරිව සමමුහුර්ත හැසිරීමයි

අපගේ ප්‍රශ්නයේ සියලුම උදාහරණ වල සිදුවන්නේ මෙයයි. පින්තූරයක් පූරණය කිරීම, තැටියෙන් පිටත ගොනුවක් පැටවීම සහ AJAX හරහා පිටුවක් ඉල්ලා සිටීම යන සියල්ලම මන්දගාමී මෙහෙයුම් වේ (නවීන පරිගණකකරණයේ සන්දර්භය තුළ).

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

var outerScopeVar;    
var img = document.createElement('img');

// Here we register the callback function.
img.onload = function() {
    // Code within this function will be executed once the image has loaded.
    outerScopeVar = this.width;
};

// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);

ඉහත කේතය තුළ, අපි ජාවාස්ක්‍රිප්ට් පූරණය lolcat.pngකරන ලෙස ඉල්ලා සිටිමු . මෙම මන්දගාමී මෙහෙයුම සිදු වූ පසු ඇමතුම් ලබා ගැනීමේ කාර්යය ක්‍රියාත්මක වනු ඇත, නමුත් මේ අතරතුර, ජාවාස්ක්‍රිප්ට් විසින් ඊළඟ කේත පේළි සැකසීම දිගටම කරගෙන යනු ඇත; එනම් alert(outerScopeVar).

අනතුරු ඇඟවීම පෙන්වන්නේ මේ නිසා ය undefined; සිට alert()වෙනුවට ප්රතිරූපය පටවා ඇත පසු වඩා, වහාම සකස් කර ඇත.

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

var img = document.createElement('img');

img.onload = function() {
    var localScopeVar = this.width;
    alert(localScopeVar);
};

img.src = 'lolcat.png';

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

එමනිසා, අපගේ සියලු උදාහරණ වලදී, function() { /* Do something */ }නැවත කැඳවීම; සියලු උදාහරණ නිවැරදි කිරීමට , අප කළ යුතුව ඇත්තේ මෙහෙයුමේ ප්‍රතිචාරය අවශ්‍ය කේතය එහි ගෙනයාම පමණි!

* තාක්ෂණික වශයෙන් ඔබටද භාවිතා eval()කළ හැකිය, නමුත් eval()මේ සඳහා නපුරකි


මගේ අමතන්නා බලා සිටින්නේ කෙසේද?

ඔබට දැනට මේ හා සමාන කේත කිහිපයක් තිබිය හැකිය;

function getWidthOfImage(src) {
    var outerScopeVar;

    var img = document.createElement('img');
    img.onload = function() {
        outerScopeVar = this.width;
    };
    img.src = src;
    return outerScopeVar;
}

var width = getWidthOfImage('lolcat.png');
alert(width);

කෙසේ වෙතත්, එය return outerScopeVarවහාම සිදුවන බව අපි දැන් දනිමු ; onloadඇමතුම් ආපසු ගැනීමේ ශ්‍රිතය විචල්‍යය යාවත්කාලීන කිරීමට පෙර . මෙය getWidthOfImage()නැවත පැමිණීමට undefinedසහ undefinedඅවදියෙන් සිටීමට හේතු වේ .

මෙය නිවැරදි කිරීම සඳහා, ඇමතුම් getWidthOfImage()ලබා ගැනීම ලියාපදිංචි කිරීම සඳහා ශ්‍රිත ඇමතුමට ඉඩ දිය යුතු අතර, පළල පිළිබඳ අනතුරු ඇඟවීම එම ඇමතුම තුළ තිබිය යුතුය.

function getWidthOfImage(src, cb) {     
    var img = document.createElement('img');
    img.onload = function() {
        cb(this.width);
    };
    img.src = src;
}

getWidthOfImage('lolcat.png', function (width) {
    alert(width);
});

... පෙර මෙන්, ගෝලීය විචල්‍යයන් ඉවත් කිරීමට අපට හැකි වූ බව සලකන්න (මේ අවස්ථාවේ දී width).


2
ඔබට වෙනත් ගණනය කිරීමක ප්‍රති results ල භාවිතා කිරීමට අවශ්‍ය නම් හෝ එය වස්තු විචල්‍යයක ගබඩා කිරීමට අවශ්‍ය නම් අනතුරු ඇඟවීම හෝ කොන්සෝලය වෙත යැවීම ප්‍රයෝජනවත් වන්නේ කෙසේද?
කෙන් ඉන්ග්‍රම්

71

මෙන්න ඉක්මන් යොමු කිරීමක් සොයන පුද්ගලයින් සඳහා වඩාත් සංක්ෂිප්ත පිළිතුරක් මෙන්ම පොරොන්දු සහ අසින්ක් / අපේක්ෂාවෙන් භාවිතා කරන උදාහරණ කිහිපයක්.

අසමමුහුර්ත ක්‍රමයක් (මේ අවස්ථාවේ දී setTimeout) අමතා පණිවිඩයක් ලබා දෙන ශ්‍රිතයක් සඳහා බොළඳ ප්‍රවේශය (එය ක්‍රියා නොකරයි) සමඟ ආරම්භ කරන්න :

function getMessage() {
  var outerScopeVar;
  setTimeout(function() {
    outerScopeVar = 'Hello asynchronous world!';
  }, 0);
  return outerScopeVar;
}
console.log(getMessage());

undefinedඇමතුම getMessageලබා ගැනීමට පෙර setTimeoutසහ යාවත්කාලීන වීමට පෙර නැවත පැමිණෙන නිසා මෙම නඩුවේ ලොග් වී ඇත outerScopeVar.

එය විසඳීමට ඇති ප්‍රධාන ක්‍රම දෙක වන්නේ ඇමතුම් සහ පොරොන්දු භාවිතා කිරීමයි :

ඇමතුම් ආපසු

මෙහි වෙනස නම්, ලබා ගත් පසු getMessageප්‍රති call callbackල නැවත ඇමතුම් කේතයට ලබා දීම සඳහා කැඳවනු ලබන පරාමිතියක් පිළිගැනීමයි .

function getMessage(callback) {
  setTimeout(function() {
    callback('Hello asynchronous world!');
  }, 0);
}
getMessage(function(message) {
  console.log(message);
});

පොරොන්දු

බහු අසමමුහුර්ත මෙහෙයුම් සම්බන්ධීකරණය කිරීම සඳහා ඒවා ස්වාභාවිකවම ඒකාබද්ධ කළ හැකි බැවින් පොරොන්දු මගින් ඇමතුම් වලට වඩා නම්‍යශීලී විකල්පයක් සපයයි. ඒ පොරොන්දු / A + සම්මත ක්රියාත්මක natively node.js (0.12+) හා තවත් බොහෝ වත්මන් බ්රව්සර ලබා ඇත, පමණක් නොව, වැනි පුස්තකාල ක්රියාත්මක bluebird හා Q .

function getMessage() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('Hello asynchronous world!');
    }, 0);
  });
}

getMessage().then(function(message) {
  console.log(message);  
});

jQuery විලම්බිත

jQuery එහි විලම්බිතයන් සමඟ පොරොන්දු වලට සමාන ක්‍රියාකාරීත්වයක් සපයයි.

function getMessage() {
  var deferred = $.Deferred();
  setTimeout(function() {
    deferred.resolve('Hello asynchronous world!');
  }, 0);
  return deferred.promise();
}

getMessage().done(function(message) {
  console.log(message);  
});

අසින්ක් / බලා සිටින්න

ඔබගේ ජාවාස්ක්‍රිප්ට් පරිසරය සඳහා asyncසහ await(Node.js 7.6+ වැනි) සහය තිබේ නම්, එවිට ඔබට asyncකාර්යයන් තුළ සමකාලීනව පොරොන්දු භාවිතා කළ හැකිය :

function getMessage () {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve('Hello asynchronous world!');
        }, 0);
    });
}

async function main() {
    let message = await getMessage();
    console.log(message);
}

main();

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

මේ සියල්ල හොඳයි, නමුත් ඔබට පරාමිතීන් සමඟ getMessage () අමතන්න අවශ්‍ය නම් කුමක් කළ යුතුද? ඉහත තත්වය ඔබ ලියන්නේ කෙසේද?
චිවාඩා

2
Hi චිවාඩා ඔබ ඇමතුම් ලබා ගැනීමේ පරාමිතිය අවසන් වරට තැබුවේ : function getMessage(param1, param2, callback) {...}.
ජොනී එච්කේ

මම ඔබේ async/awaitනියැදිය උත්සාහ කරමි , නමුත් මම ගැටළු වලට මුහුණ දෙමි. A ක්ෂණිකව ස්ථාපනය කරනවා වෙනුවට new Promise, මම .Get()ඇමතුමක් ගන්නා අතර එබැවින් කිසිදු resolve()ක්‍රමයකට ප්‍රවේශ විය නොහැක . මේ අනුව මම getMessage()පොරොන්දුව නැවත ලබා දෙනවා මිසක් ප්‍රති .ලය නොවේ. මේ සඳහා වැඩ කරන වාක්‍ය ඛණ්ඩයක් පෙන්වීමට ඔබට ඔබේ පිළිතුර ටිකක් සංස්කරණය කළ හැකිද?
ඉන්ටෙක්ස්

IntInteXX .Get()ඇමතුමක් ලබා ගැනීම ගැන ඔබ අදහස් කරන්නේ කුමක්දැයි මට විශ්වාස නැත . නව ප්‍රශ්නයක් පළ කිරීම වඩාත් සුදුසුය.
ජොනී එච්කේ

55

පැහැදිලිව කිවහොත්, කුසලානය නියෝජනය කරයි outerScopeVar.

අසමමුහුර්ත කාර්යයන් සමාන වේ ...

කෝපි සඳහා අසමමුහුර්ත ඇමතුම


14
සමමුහුර්තව ක්‍රියා කිරීමට උත්සාහ කරන විට තත්පර 1 ට කෝපි පානය කිරීමට උත්සාහ කිරීම සහ මිනිත්තු 1 කින් ඔබේ උකුලට වත් කිරීම.
Teepeemm

එය පැහැදිලිව ප්‍රකාශ කළේ නම්, මම නොසිතමි.
broccoli2000

2
@ broccoli2000 එයින් මා අදහස් කළේ ප්‍රශ්නය පැහැදිලිය, නමුත් කුසලානය චිත්‍රයෙන් නිරූපණය කරන්නේ කුමක්ද යන්න පැහැදිලිය :)
ජොහැන්නස් ෆැරන්ක්‍රග්

14

අනෙක් පිළිතුරු විශිෂ්ට වන අතර මට අවශ්‍ය වන්නේ මේ සඳහා සෘජු ඉදිරි පිළිතුරක් සැපයීමයි. JQuery අසමමුහුර්ත ඇමතුම් වලට සීමා කිරීම

සියලුම අජැක්ස් ඇමතුම් ( $.getහෝ $.postහෝ ඇතුළුව $.ajax) අසමමුහුර්ත වේ.

ඔබේ ආදර්ශය සලකා බලන්න

var outerScopeVar;  //line 1
$.post('loldog', function(response) {  //line 2
    outerScopeVar = response;
});
alert(outerScopeVar);  //line 3

කේත ක්‍රියාත්මක කිරීම 1 වන පේළියේ සිට ආරම්භ වන අතර විචල්‍යය ප්‍රකාශයට පත් කරන අතර 2 වන පේළියේ අසමමුහුර්ත ඇමතුම (එනම්, පශ්චාත් ඉල්ලීම) සහ එය 3 වන පේළියේ සිට ක්‍රියාත්මක කිරීම දිගටම කරගෙන යයි.

තැපැල් ඉල්ලීම සම්පූර්ණ කිරීමට තත්පර 10 ක් ගතවනු ඇතැයි අපි කියමු outerScopeVar.

අත්හදා බැලීමට,

var outerScopeVar; //line 1
$.post('loldog', function(response) {  //line 2, takes 10 seconds to complete
    outerScopeVar = response;
});
alert("Lets wait for some time here! Waiting is fun");  //line 3
alert(outerScopeVar);  //line 4

දැන් ඔබ මෙය ක්‍රියාත්මක කරන විට, ඔබට 3 වන පේළියේ අනතුරු ඇඟවීමක් ලැබෙනු ඇත. දැන් තැපැල් ඉල්ලීම යම් වටිනාකමක් ලබා දී ඇති බවට ඔබට සහතික වන තෙක් ටික වේලාවක් රැඳී සිටින්න. ඔබ OK ක්ලික් කළ විට, ඇඟවීම් කොටුව මත, ඊළඟ ඇඟවීම මඟින් අපේක්ෂිත අගය මුද්‍රණය කරනු ඇත, මන්ද ඔබ ඒ සඳහා බලා සිටි බැවිනි.

සැබෑ ජීවිතයේ දී, කේතය බවට පත්වේ,

var outerScopeVar;
$.post('loldog', function(response) {
    outerScopeVar = response;
    alert(outerScopeVar);
});

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


or by waiting on the asynchronous callsයමෙක් එය කරන්නේ කෙසේද?
ඉන්ටෙක්ස්

TInteXX ඇමතුම් ලබා ගැනීමේ ක්‍රමයක් භාවිතා කිරීමෙන්
තේජා

ඔබට ඉක්මන් සින්ටැක්ස් උදාහරණයක් තිබේද?
ඉන්ටෙක්ස්

11

මෙම සියලු අවස්ථා වලදී outerScopeVarවෙනස් කරන ලද හෝ අගයක් අසමමුහුර්තව හෝ පසු කාලයක සිදුවෙමින් පවතී (යම් සිදුවීමක් සිදුවනු ඇතැයි බලා සිටීම හෝ සවන් දීම), ඒ සඳහා වර්තමාන ක්‍රියාත්මක කිරීම බලා නොසිටිනු ඇත .මෙම අවස්ථාවන්හිදී වත්මන් ක්‍රියාත්මක කිරීමේ ප්‍රවාහයේ ප්‍රති results ලouterScopeVar = undefined

එක් එක් උදාහරණ සාකච්ඡා කරමු (සමහර සිදුවීම් සිදුවීමට අසමමුහුර්තව හෝ ප්‍රමාද වූ කොටස මම සලකුණු කළෙමි):

1.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

මෙන්න අපි ඊළඟ රේඛා වත්මන් ක්රියාත්මක අඛණ්ඩ image.Then බව විශේෂයෙන් event.Here පැටවීම මත ක්රියාත්මක කරනු ලබන යම් eventlistner ලියාපදිංචි img.src = 'lolcat.png';හා alert(outerScopeVar);මේ අතර මෙම අවස්ථාවට සිදු විය හැක. එනම්, img.onloadයොමු කරන ලද රූපය පැටවීම සඳහා සමකාලීනව බලා සිටින්න. පහත දැක්වෙන සියලු උදාහරණ මෙය සිදුවනු ඇත- සිද්ධිය වෙනස් විය හැකිය.

2.

2

මෙහිදී කල් ඉකුත් වීමේ සිදුවීම භූමිකාව ඉටු කරයි, එය නියමිත වේලාවට පසුව හසුරුවන්නාට ආයාචනා කරනු ඇත. මෙන්න එය 0, නමුත් තවමත් එය අසමමුහුර්ත සිදුවීමක් ලියාපදිංචි කරන අතර එය ක්‍රියාත්මක කිරීම සඳහා අවසාන ස්ථානයට එකතු කරනු ඇත Event Queue, එමඟින් සහතික කළ ප්‍රමාදය ඇති කරයි.

3.

රූප විස්තරය මෙහි ඇතුළත් කරන්න මෙවර අජැක්ස් ඇමතුම.

4.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

නෝඩය අසමමුහුර්ත කේතීකරණයේ රජෙකු ලෙස සැලකිය හැකිය. මෙහි සලකුණු කරන ලද ශ්‍රිතය ඇමතුම් ආපසු හසුරුවන්නෙකු ලෙස ලියාපදිංචි කර ඇති අතර එය නිශ්චිත ගොනුව කියවීමෙන් පසු ක්‍රියාත්මක වේ.

5.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

නිසැකවම පොරොන්දුව (අනාගතයේදී යමක් කරනු ඇත) අසමමුහුර්ත වේ. බලන්න ජාවාස්ක්‍රිප්ට් හි විලම්බිත, පොරොන්දු සහ අනාගතය අතර ඇති වෙනස්කම් මොනවාද?

https://www.quora.com/Whats-the-difference-between-a-promise-and-a-callback-in-Javascript

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.