Javascript 回调执行得太早

Javascript 回调执行得太早,javascript,node.js,loops,foreach,callback,Javascript,Node.js,Loops,Foreach,Callback,我正在努力解决一个我无法回避的问题 我使用NodeJS从restapi请求数据。对于这个程序,我首先检索一个数据数组,然后根据第一个数组的id从另一个端点请求一些详细信息 我在带有回调的第一个函数调用中使用foreach循环,然后在foreach循环中使用另一个函数调用来获取详细信息 我的经验是,第二个函数在检索响应之前进行回调 我已通过以下示例代码再现了该问题: console.log('Program start') // Executing program getFirstname(fu

我正在努力解决一个我无法回避的问题

我使用NodeJS从restapi请求数据。对于这个程序,我首先检索一个数据数组,然后根据第一个数组的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
如您所见,有几个记录的值未定义。此外,我还添加了一个setTimeout来模拟每个rest调用都需要几秒钟的时间。发生的情况是,所有查询都会立即被触发,然后在所有响应同时返回之前2秒

我希望它等待每一秒的rest调用,然后返回结果

我如何解决这个问题

致以最良好的祝愿,
Christian

未定义的原因是数据数组的长度为4,索引从0到3,但id的范围为0到4。这意味着当您引用数据[4]时,您会得到未定义的数据。

您未定义的原因是,您的数据数组的长度为4,索引从0到3,但id的范围为0到4。这意味着,当您引用数据[4]时,您将得到未定义的数据。

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

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,以便在数据数组中使用。请记住,数组是基于0的,因此数据[4]=未定义…

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

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,以便在数据数组中使用。请记住,数组是基于0的,因此数据[4]=未定义…

您的右侧。这实际上是示例代码中的一个输入错误,但我的真实代码有这个问题。你说的对。这实际上是示例代码中的一个输入错误,但我的真实代码有这个问题。参考对前面答案的评论。我可以看到我在那里输入了一个错别字,我的例子确实有效。这并不能解决我真实代码中的问题:@chranmat不用担心。你能发布你的实际代码吗?请参考前面答案的评论。我可以看到我在那里输入了一个错别字,我的例子确实有效。这并不能解决我真实代码中的问题:@chranmat不用担心。你能公布你的实际代码吗?