为什么 await sleep 提前退出 for 循环?
Why does an await sleep exits a for loop early?
我尝试在单击 next/previous 按钮时为音乐应用程序制作淡入淡出效果;
我有这个睡眠功能:
const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
按下按钮时的功能:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
和衰减函数
async function fadeOut(soundtrack){
for (var i = 1.0; i > 0; i-= 0.01)
{
console.log(i);
console.log(soundtrack.volume);
soundtrack.volume = i;
await sleep(2000);
}
}
async function fadeIn(soundtrack){
for (var i = 0; i <= 1; i+= 0.01)
{
console.log(i);
console.log(soundtrack.volume);
soundtrack.volume = i;
await sleep(100);
}
}
问题是 fadeOut 根本不起作用,它进入 for 循环进行 1 次迭代然后存在。
同时,淡入效果完美。我就是不明白。顺便说一句,这是我的第一个 javascript 爱好项目。
函数 returns 到达 await
是正常的。它 return 是一个承诺。您必须确保调用者还等待 that 承诺的解决,它只会在第一个函数完成其所有任务时解决。
所以:
async function nextSong() {
//^^^^
songIndex = (songIndex + 1) % songs.length;
await fadeOut(audio);
//^^^^^
await loadSong(songs[songIndex]);
await playSong();
await fadeIn(audio);
}
我在这里假设 loadSong
和 playSong
也 return 承诺,因此这些调用也需要 await
运算符。
看起来问题可能出在您的 nextSong
函数上。您正在调用多个 async
函数,每个函数 运行 彼此独立。您希望 fadeOut
在 loading/playing 下一首歌曲之前完成。
有两种解决方法。第一个是使用 .then
在 淡出当前歌曲后 加载下一首歌曲:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio).then(() => {
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
});
}
或者,您可以使函数 async
和 await
调用 fadeOut 函数:
async function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
await fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
同意前面的回答。我还认为,鉴于这是一个项目,您可以在不使用 async/await.
的情况下创建具有这些功能的音乐播放器
我在 HTML 中使用 archive.org mp3 url 作为音频标签创建了一个片段,并且能够让它们在跳过歌曲时淡入淡出。
另外一个想法,既有函数声明又有表达式。了解其中的区别很重要。函数声明在执行任何代码之前加载,而函数表达式仅在解释器到达该行代码时加载。
函数表达式
alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; }
函数声明
alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; }
当您想在全局范围内创建函数并使其在整个代码中可用时,请使用函数声明。使用函数表达式限制函数可用的位置,保持全局范围简洁,并保持语法简洁。
除非需要函数声明,否则我更喜欢在整个代码中使用函数表达式。
如果您想练习使用 async/await,您可以查看这些其他 Whosebug 问题。
How and when to use ‘async’ and ‘await’
What is the use case for async/await?
我尝试在单击 next/previous 按钮时为音乐应用程序制作淡入淡出效果; 我有这个睡眠功能:
const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
按下按钮时的功能:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
和衰减函数
async function fadeOut(soundtrack){
for (var i = 1.0; i > 0; i-= 0.01)
{
console.log(i);
console.log(soundtrack.volume);
soundtrack.volume = i;
await sleep(2000);
}
}
async function fadeIn(soundtrack){
for (var i = 0; i <= 1; i+= 0.01)
{
console.log(i);
console.log(soundtrack.volume);
soundtrack.volume = i;
await sleep(100);
}
}
问题是 fadeOut 根本不起作用,它进入 for 循环进行 1 次迭代然后存在。 同时,淡入效果完美。我就是不明白。顺便说一句,这是我的第一个 javascript 爱好项目。
函数 returns 到达 await
是正常的。它 return 是一个承诺。您必须确保调用者还等待 that 承诺的解决,它只会在第一个函数完成其所有任务时解决。
所以:
async function nextSong() {
//^^^^
songIndex = (songIndex + 1) % songs.length;
await fadeOut(audio);
//^^^^^
await loadSong(songs[songIndex]);
await playSong();
await fadeIn(audio);
}
我在这里假设 loadSong
和 playSong
也 return 承诺,因此这些调用也需要 await
运算符。
看起来问题可能出在您的 nextSong
函数上。您正在调用多个 async
函数,每个函数 运行 彼此独立。您希望 fadeOut
在 loading/playing 下一首歌曲之前完成。
有两种解决方法。第一个是使用 .then
在 淡出当前歌曲后 加载下一首歌曲:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio).then(() => {
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
});
}
或者,您可以使函数 async
和 await
调用 fadeOut 函数:
async function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
await fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
同意前面的回答。我还认为,鉴于这是一个项目,您可以在不使用 async/await.
的情况下创建具有这些功能的音乐播放器我在 HTML 中使用 archive.org mp3 url 作为音频标签创建了一个片段,并且能够让它们在跳过歌曲时淡入淡出。
另外一个想法,既有函数声明又有表达式。了解其中的区别很重要。函数声明在执行任何代码之前加载,而函数表达式仅在解释器到达该行代码时加载。
函数表达式
alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; }
函数声明
alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; }
当您想在全局范围内创建函数并使其在整个代码中可用时,请使用函数声明。使用函数表达式限制函数可用的位置,保持全局范围简洁,并保持语法简洁。
除非需要函数声明,否则我更喜欢在整个代码中使用函数表达式。
如果您想练习使用 async/await,您可以查看这些其他 Whosebug 问题。
How and when to use ‘async’ and ‘await’
What is the use case for async/await?