1

所以,我有一个在 DOM 完全加载时运行的 init 函数:

function init() 
{
    TerrainObj.load_terrain();
    TerrainObj.generate_display_layer(PlayerObj);
    GameObj.update();
    ScreenObj.draw_screen(TerrainObj);
    ScreenObj.update_screen(TerrainObj);
    mainloop();
}

第一个方法,TerrainObj.load_terrain()发出一个 AJAX 请求:

load_terrain: function()
{
    var settings = {
        type: "GET",
        url: "data/map.txt",
        aysnc: false
    };

    $.ajax(settings).done(function(result) 
    {
        this.terrain = result.split("\n");
        for (var i = 0; i < this.terrain.length; i++)
        {
            this.terrain[i] = this.terrain[i].split("")
        }
        console.log(this.terrain);
    });
}

问题是,在我们的init()函数中,后面的大多数方法都TerrainObj.load_terrain()需要存在TerrainObj.terrain array,但是在 AJAX 请求完成并填充该变量之前调用它们。当每个函数运行以检查订单时,我会发出一条小消息,我得到了这个:

Ran TerrainObj.load_terrain()
Ran ScreenObj.draw_screen()
Uncaught TypeError: Cannot read property '0' of undefined 
[Array[55], Array[55], ... ]

因此,您可能会看到,ScreenObj.draw_screen需要 TerrainObj.terrain 的 ,在请求完成之前已经运行,并且有一个TypeError尝试引用我们的对象的时间。它还没有准备好!最后一条消息是console.log()来自该load_terrain方法的消息,表示该.done函数随后运行。

我该怎么做才能等到 AJAX 请求完成后再继续我的程序?

4

2 回答 2

5

Javascript 是一种事件驱动语言。您没有主循环,但您有触发正在发生的事情的事件。

在这里,您的 ajax 调用的完成触发了地形的后续设置。因此将功能分为两部分:

init: function() 
{
    TerrainObj.load_terrain();
},
init_terrain: function()
{
    TerrainObj.generate_display_layer(PlayerObj);
    GameObj.update();
    ScreenObj.draw_screen(TerrainObj);
    ScreenObj.update_screen(TerrainObj);
    mainloop();
},
load_terrain: function()
{
    var settings = {
        type: "GET",
        url: "data/map.txt",
        aysnc: false
    };

    $.ajax(settings).done(function(result) 
    {
        this.terrain = result.split("\n");
        for (var i = 0; i < this.terrain.length; i++)
        {
            this.terrain[i] = this.terrain[i].split("")
        }
        this.init_terrain();
    });
}
于 2013-09-28T12:22:57.683 回答
1

检查以下代码块中的注释部分

    $.ajax(settings).done(function(result) 
    {
        this.terrain = result.split("\n");
        for (var i = 0; i < this.terrain.length; i++)
        {
            this.terrain[i] = this.terrain[i].split("")
        }
        /*******************************************/
        //Place a new function call here, to the function that contains the calls to your 
        //functions, or other logic, that require the array to be populated.
        /*******************************************/
    });
于 2013-09-28T12:46:40.267 回答