在 JavaScript 中使用回调函数的替代方案?
Alternative to using callback function in JavaScript?
我试图在第一个函数的滚动动画结束后调用第二个函数。我已经看到在类似情况下使用回调函数,但它们似乎更麻烦且难以阅读。有没有更简单或更干净的方法来达到相同的结果?
$('#nav_experience').click(function scrollToExperience(){
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500);
})
function navbarExperienceActive(){
scrollToExperience(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
我也很欣赏第二个函数非常重复,可能有更优雅的方式来编写它,我对 JavaScript 比较陌生。
我们过去使用回调的情况的一种现代方法是使用 promises,当与 async
函数和 await
结合使用时特别有效. (从概念上讲,“promises”有很多名称——promises、futures、deferreds……)
Promise 本身仍然使用回调,但通过提供一种标准化形式来传递未来回调的 promises,它们显着改进了过去将回调作为参数传递的代码。
您的 scrollToExperience
可能看起来像这样,例如:
function scrollToExperience(){
return new Promise(resolve => {
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500, resolve);
});
}
navbarExperienceActive
可能会这样使用它:
function navbarExperienceActive(){
scrollToExperience().then(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
从表面上看,变化不大;您仍然必须传递回调。但是,如果 navbarExperienceActive
必须将其与其他异步操作结合起来,以其他方式将其链接起来,等等,使用 promises 会使代码库之间的操作更简单、更标准。
但是如果 navbarExperienceActive
是一个 async
函数,它可以使用 await
:
async function navbarExperienceActive(){
await scrollToExperience();
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
}
它仍然使用 promises,但代码是根据其简单的逻辑流程编写的,而不是担心必须等待 scrollToExperience
完成的事实。
一个async
函数总是returns一个承诺;当你在 async
函数中使用 await
时,如果你传递的值是一个承诺 (hand-waves details about "thenables"),它returns 它的 promise 然后根据你正在 await
ing 的 promise 发生的事情来解决这个 promise(and/or 它后面的逻辑)。
我应该注意到上面 scrollToExperience
返回的承诺有点不寻常,因为它总是履行承诺,它从不拒绝它。使用其承诺的代码依赖于它从不拒绝其承诺的事实。
不过,一般来说,重要的是要确保要么处理 promise 拒绝,要么将 promise 链 传递给其他可以处理的东西。那是 async
函数让生活更简单的另一个地方:它们自动传播 promise 拒绝,这与同步函数自动传播异常的方式完全相同。
我试图在第一个函数的滚动动画结束后调用第二个函数。我已经看到在类似情况下使用回调函数,但它们似乎更麻烦且难以阅读。有没有更简单或更干净的方法来达到相同的结果?
$('#nav_experience').click(function scrollToExperience(){
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500);
})
function navbarExperienceActive(){
scrollToExperience(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
我也很欣赏第二个函数非常重复,可能有更优雅的方式来编写它,我对 JavaScript 比较陌生。
我们过去使用回调的情况的一种现代方法是使用 promises,当与 async
函数和 await
结合使用时特别有效. (从概念上讲,“promises”有很多名称——promises、futures、deferreds……)
Promise 本身仍然使用回调,但通过提供一种标准化形式来传递未来回调的 promises,它们显着改进了过去将回调作为参数传递的代码。
您的 scrollToExperience
可能看起来像这样,例如:
function scrollToExperience(){
return new Promise(resolve => {
$('html, body').animate({
scrollTop: $('#Experience').offset().top
}, 500, resolve);
});
}
navbarExperienceActive
可能会这样使用它:
function navbarExperienceActive(){
scrollToExperience().then(function(){
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
});
}
从表面上看,变化不大;您仍然必须传递回调。但是,如果 navbarExperienceActive
必须将其与其他异步操作结合起来,以其他方式将其链接起来,等等,使用 promises 会使代码库之间的操作更简单、更标准。
但是如果 navbarExperienceActive
是一个 async
函数,它可以使用 await
:
async function navbarExperienceActive(){
await scrollToExperience();
$('#nav_profile').removeClass('active');
$('#nav_education').removeClass('active');
$('#nav_contact').removeClass('active');
$('#nav_experience').addClass('active');
}
它仍然使用 promises,但代码是根据其简单的逻辑流程编写的,而不是担心必须等待 scrollToExperience
完成的事实。
一个async
函数总是returns一个承诺;当你在 async
函数中使用 await
时,如果你传递的值是一个承诺 (hand-waves details about "thenables"),它returns 它的 promise 然后根据你正在 await
ing 的 promise 发生的事情来解决这个 promise(and/or 它后面的逻辑)。
我应该注意到上面 scrollToExperience
返回的承诺有点不寻常,因为它总是履行承诺,它从不拒绝它。使用其承诺的代码依赖于它从不拒绝其承诺的事实。
不过,一般来说,重要的是要确保要么处理 promise 拒绝,要么将 promise 链 传递给其他可以处理的东西。那是 async
函数让生活更简单的另一个地方:它们自动传播 promise 拒绝,这与同步函数自动传播异常的方式完全相同。