回调执行得太早

时间:2018-11-12 20:21:24

标签: javascript node.js loops foreach callback

我正在为无法解决的问题而苦苦挣扎。

我正在使用NodeJS从Rest API的请求数据。对于该程序,我首先检索一个数据数组,然后根据第一个数组的ID向另一个端点请求一些详细信息。

我在第一个带有回调的函数调用中使用一个foreach循环,然后在foreach循环中使用另一个函数来获取详细信息。

我的经验是第二个函数在检索响应之前会回调。

我设法用以下示例代码重现了该问题:

console.log('Program start')

// Executing program
getFirstname(function(person) {

    person.forEach(firstname => {

        getSurname(firstname.id, function(lastname) {
            console.log(`${firstname.value} ${lastname}`)
        });

    });
})

// Emulating REST API´s
function getFirstname(callback) {

    console.log('Returning list of firstnames')

    let data = [
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
        {id: 0, value: 'John'},
        {id: 2, value: 'Andy'},
        {id: 3, value: 'Jimmy'},
        {id: 4, value: 'Alex'},
    ]

    callback(data);
}

function getSurname(id, callback) {

    console.log(`Querying for lastname id ${id}`)

    let data = [
        'Andersen',
        'Johsen',
        'Falon',
        'Alexander',
    ]

    setTimeout(() => {
        callback(data[id]);
    }, 2000);
}

这是程序的结果:

Program start
Returning list of firstnames
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
Querying for lastname id 0
Querying for lastname id 2
Querying for lastname id 3
Querying for lastname id 4
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined
John Andersen
Andy Falon
Jimmy Alexander
Alex undefined

如您所见,有几条记录的值为undefined。另外,我还添加了setTimeout来模拟每个剩余呼叫都需要几秒钟。发生的情况是,所有查询都会立即触发,然后等待2秒钟,所有响应才能同时返回。

我希望它能够等待第二次休息电话,然后返回结果。

我该如何解决这个问题?

最好的问候, 克里斯蒂安

2 个答案:

答案 0 :(得分:3)

您拥有undefined的原因是因为您的data数组的长度为4(索引从 0到3 ),但是您的{{1} }的范围是0到 4 。这意味着当您引用id时,您会得到data[4]

答案 1 :(得分:2)

您的回调没有问题。数据,但是,不正确。见下文:

function getSurname(id, callback) {

    console.log(`Querying for lastname id ${id}`)

    let data = [
        'Andersen',
        'Johsen',
        'Falon',
        'Alexander',
    ]

    setTimeout(() => {
        callback(data[id]);
    }, 2000);
}

每次调用Alex时,您都会传递ID 4以便在data数组中使用。请记住,数组基于0,因此data[4] = undefined ...

相关问题