Reputation: 13
I try to make a fade in & out effect for a music application when I click the next/previous button; I have this sleep function:
const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
the function when the button is pushed:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
and the fading functions
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);
}
}
The problem is fadeOut doesn't work at all, it goes in the for loop for 1 iteration and then exists. Meanwhile, fadeIn works perfectly. I just can't understand. Btw this is my first javascript hobby project.
Upvotes: 1
Views: 155
Reputation: 74
I agree with the previous answers. I also think that, given this is a project, you can create a music player with these features without using async/await.
I created a snipped using archive.org mp3 urls as audio tags in HTML, and was able to get them to fade in and out when skipping songs.
One other thought, there are both function declarations and expressions. It is important to understand the difference. Function declarations load before any code is executed while Function expressions load only when the interpreter reaches that line of code.
Function Expression
alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; }
Function Declaration
alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; }
Use function declarations when you want to create a function on the global scope and make it available throughout your code. Use function expressions to limit where the function is available, keep your global scope light, and maintain clean syntax.
I prefer using function expressions throughout my code unless a function declaration is necessary.
If you are wanting to practice using async/await, you could see these other stackoverflow questions.
How and when to use ‘async’ and ‘await’
What is the use case for async/await?
Upvotes: -1
Reputation: 95
It looks like the issue might be coming from your nextSong
function. You are calling multiple async
functions, which are each running independently of each other. You want fadeOut
to complete before loading/playing the next song.
There's two solutions to this. The first one would be to use .then
to load the next song after fading out the current song:
function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
fadeOut(audio).then(() => {
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
});
}
Or, alternatively, you can make the function async
and await
the fadeOut function call:
async function nextSong() {
songIndex++;
if (songIndex > songs.length - 1) {
songIndex = 0;
}
await fadeOut(audio);
loadSong(songs[songIndex]);
playSong();
fadeIn(audio);
}
Upvotes: 0
Reputation: 350272
It is normal that a function returns when it gets to an await
. It returns a promise. You must make sure that the caller also awaits the resolution of that promise, which will only resolve when the first function finishes all its tasks.
So:
async function nextSong() {
//^^^^
songIndex = (songIndex + 1) % songs.length;
await fadeOut(audio);
//^^^^^
await loadSong(songs[songIndex]);
await playSong();
await fadeIn(audio);
}
I am assuming here that loadSong
and playSong
also return promises, and so these calls also need the await
operator.
Upvotes: 2