سؤال

لدي وظيفة أود من خلالها إعادة قيمة كسلسلة من الأحداث كلما تم النقر على زر. ومع ذلك ، لا يمكنني معرفة كيفية استرداد القيمة من onReadyStateChange. كيف يمكنني صنعه حتى أتمكن من العودة vicArray[vicID]?

function selectVictim()
{
var vicString;
var vicArray;
var vicID;

var params = "url=queenofsheep.com/Sheep/victims.php";
var request = new ajaxRequest();

request.open("POST", "victims.php", true);
request.setRequestHeader("Content-Type",
                             "application/x-www-form-urlencoded");
request.setRequestHeader("Content-Length", params.length);
request.setRequestHeader("Connection", "close");

request.send(params);

request.onreadystatechange = function ()
{
    if (this.readyState == 4)
    {
        if (this.status == 200)
        {
            if (this.responseText != null )
            {
                vicString = this.responseText;
                vicArray = JSON.parse(vicString);
                vicID = Math.floor(Math.random() * (vicArray.length - 1));
            }
            else alert("Ajax error: No data received");
        }
        else alert("Ajax Error: " + this.statusText);
    }
}
alert(vicArray[vicID]);
}
هل كانت مفيدة؟

المحلول

لا يمكنك. لك onreadystatechange يتم استدعاء المعالج لفترة طويلة بعد، بعدما ال selectVictim عودة الوظيفة.

ما لديك هنا هو ، إذن أن تقول ، "وظائف غير متزامنة" - أي وظائف تولد قيمة الإرجاع الخاصة بها ليس على الفور ، ولكن بعد عملية غير متزامنة معينة.

للتعامل مع هذا ، يتعين على المرء استخدام رد اتصال لتوفير قيمة الإرجاع:

function selectVictim( callback )
{
    ...
    ...

    request.onreadystatechange = function() {
        ...
        vicArray[vicID] = ...;
        callback( vicArray[vicID] );
    }
}

لاحظ ال callback جدال. كل من يسمي هذه الوظيفة ، يجب أن يوفر وظيفة أخرى لهذه الوسيطة. ثم لاحظ كيف selectVictim يستدعي رد الاتصال عندما تكون قيمة الإرجاع جاهزة.

الآن أينما تتصل selectVictim, ، يجب عليك تعديل الكود الخاص بك من:

function someFunc()
{
    doSomething();

    var vic = selectVictim();

    domeSomethingElseWithVictim( vic );
}

إلى:

function someFunc()
{
    doSomething();

    selectVictim( function( vic ) {

        domeSomethingElseWithVictim( vic );

    } );
}

بسيطا بما فيه الكفاية؟

نصائح أخرى

أود استخدام رد الاتصال ، حيث يمكنك تمرير الوظيفة التي يتم تشغيلها بمجرد أن تكون الاستجابة جاهزة.

يضيف callback كبرام:

function selectVictim(callback)

وثم:

vicString = this.responseText;
vicArray = JSON.parse(vicString);
vicID = Math.floor(Math.random() * (vicArray.length - 1));
if (callback) {
 callback(vicID);
}

عندما تتصل بالوظيفة ، يمكنك القيام بذلك:

selectVictim(function(vicID){ 
  console.log('This is the id: ', vicID); 
});

يمكنك أيضًا تمرير الوظيفة كقيمة إذا كنت تفضل عدم القيام بذلك مباشرة. ملاحظة: يصبح الأمر صعبًا بعض الشيء إذا قمت بتقديم الكثير من الطلبات وتحتاج إلى الحفاظ على الترتيب الذي تم تقديمه به ، ولكن هناك طرق للتعامل مع ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top