I have a simple JavaScript that loads sounds:
prefix = 'modules/sounds/';
_sounds = ['nameOfSound','nameOfSound','nameOfSound'];
for (var sound in _sounds) {
if (_sounds.hasOwnProperty(sound)) {
var cached = _sounds[sound];
cached.audio = new Audio(prefix + cached.src);
}
}
}
All is being cached here, and then in angular I just have a service that does the following function:
this.play = function(trackName) {
_sounds[trackName].audio.play();
};
What I want is a simple promise for the sound, so when I call it, I will have something like this:
soundService.play('boom').then(function(){
do something here
});
Is that even possible?
I have a simple JavaScript that loads sounds:
prefix = 'modules/sounds/';
_sounds = ['nameOfSound','nameOfSound','nameOfSound'];
for (var sound in _sounds) {
if (_sounds.hasOwnProperty(sound)) {
var cached = _sounds[sound];
cached.audio = new Audio(prefix + cached.src);
}
}
}
All is being cached here, and then in angular I just have a service that does the following function:
this.play = function(trackName) {
_sounds[trackName].audio.play();
};
What I want is a simple promise for the sound, so when I call it, I will have something like this:
soundService.play('boom').then(function(){
do something here
});
Is that even possible?
Share Improve this question edited May 6, 2015 at 7:27 Mast 1,8945 gold badges32 silver badges47 bronze badges asked May 6, 2015 at 7:16 totothegreattotothegreat 1,6434 gold badges28 silver badges62 bronze badges 2- Do you have a plain callback solution? Are there any events for the end of the sound? – Bergi Commented May 6, 2015 at 7:20
- well that why im asking, how could i have a callback in the end of the sound? – totothegreat Commented May 6, 2015 at 7:29
3 Answers
Reset to default 10You can make a generic object that you can implement to suit your setup:
function play(url) {
return new Promise(function(resolve, reject) { // return a promise
var audio = new Audio(); // create audio wo/ src
audio.preload = "auto"; // intend to play through
audio.autoplay = true; // autoplay when loaded
audio.onerror = reject; // on error, reject
audio.onended = resolve; // when done, resolve
audio.src = path + url + suffix; // just for example
});
}
Now you can call:
play("boom").then(function() {
});
There is little point in caching audio elements due their buffering behavior. Indicating preload will tell browser that you will want to play through the audio file. In my opinion this is also nicer to the client and the system.
Example
function play(url) {
return new Promise(function(resolve, reject) { // return a promise
var audio = new Audio(); // create audio wo/ src
audio.preload = "auto"; // intend to play through
audio.autoplay = true; // autoplay when loaded
audio.onerror = reject; // on error, reject
audio.onended = resolve; // when done, resolve
audio.src = url
});
}
play(sample).then(function() {
alert("Done!");
})
<script>
var sample = "data:audio/wav;base64,UklGRiAOAABXQVZFZm10IBAAAAABAAEA71YAAO9WAAABAAgAZGF0YfsNAACCgoKAgYKCgoKCgoGCgoGBgIB/foCAf35+fn19fX1+foCCgYGAgICAfn5+fnx8fn5/f3+AgICBgYKCg4OCgIB/fn5+gIB/gIGBgoGAf4CAgYB+fn5+fXx8fHx9fn59fX1+foB/f39+gIGAgIGBgIB+f4CAgICAgH+AgoKBgIGCgoKChYWBfHp5eHh5enx/goSGiYqMi4mHhoaEhIOCgH58fHx8fHx+fn5/gICAgYGCgoKDhIODgoCBgYCAgICAf319fn59fn5+fn+Afn6AgYCBgYCAf36AgICAgH5+f4CAgIB+fn59fHx+fn5/gYGBgoOEgoGBgYB+fn59f35+gIB+fn+AgICBgICAfn+AgICCgYCBgYGCgoKCgICBgH+AgICAgIGCgoGAgX9/foCAgICAgIB/gICAgYB+gIGCgoKCgICAf4CCg4KBgYCAfn6AgH99e3x9fXx8fH5/f4CAgICAgIGCgoOEgoKCg4OCgoKCgICAgICAgYKCgoKCgYCBgYKCgoKCgoCAgYF+fn5/gICAgH59foCAgX9+gIB+fX19fn+AgH5/f3+Afn19fX5/gICAf4CAgH59fX6AgH5+gICAf4CAgICAgYKBgoGAfn6AgICAgIKCgICAgICAf35+fn59fX1+fn6AgH9+gIGAf4CAgYCAgICBgYB/fn+Bg4F/foGDgn59gISEgn5+g4aFgX+AhIWEfnyBhoSAfH2Cg396en6Eg357foSGgXx9hIeEfnuAhoZ+en6FhoF7fYSIhH16foSCenl+g4R/eXuChX55eoCCfHd5foJ+enp+hIF6e4KEgXt7goWBe3yChoJ7fISGgXp8g4WAfH6Eh4F6fYSGgHp9hIaAe3+GhoB7gIeGfnyChoN8e4KGg3x6gYaBenyEhn95fISGfnp+h4Z8eH+Ggnl6goiAd3iEiIB4fImKgHh+h4R5cnmGhXdzfoiDd3aAioR4eYaMgnV3hoyCdXmJjoJ2fIqMfnR6jI5/c3uMjn50fo6PfnJ7jY18cnuMjnpteY6Oem14jI56bXmOjnprdo6Se2h0jZJ7Z3GOl4BmbIqZgmZqip2HZGeKn4plZIaklGlggqKWalp4nppxWXKdontZaZOkhFxhi6eTZlyApp5yWHGeq4RYXoqolGNVd6Gfc1ZrmauKXFuHrJtnU3Siq35TX5Cxll5Sfq6rck5ooLaNVliOuaNkTXKnsH1MW5K2m11JdKqxfkxalLiaWkh0rrV5RFaYwJ1VQXe3t3ZDW52+llFGfrq2ckBbnsGWUEaAtq9uQl6evJBORn60sXREXJy+l1NCdrO0dD9VmL6eWD5wsbl8QFGUvaJeQ26tvIRIU5C6pGNEaqa5jVBOhLWvckZfnLuZWkh1rLSCTlWKs6hxTmSXsZReTnKirINUVoSsqHhSYJGwmmhTb5uqjmFWeKKog1hZgKSieVZgiaWacllqkKiacVttk6eWcF1xlKSTcWBykqKRbV5xkqKSbVprkKWWbFRok6yYalFqmbCVYExtnrCQXE9wnrCTYlNznaqPY1Z0mqaOZFZylqKMZlpykp6MbmN0jZeMdWdziJKNem5zhI6LfXN2goqHfXZ3gIeEfnt7foCBgYF+fn1+goSDfXp8goeHfnd4gIiKgnZ1fomKgXZ2foeJgnd0e4SJhn54eoKKjYV4dX6KkYt6cXiGkIx7bXOGkpGAcHKElJOCb26Aj5GGdG55iY+KfXJ0g46QhHNteY2Uindsc4aSjHxvcICOj4FycXuIjId8dHN7iIyGe3N1go+OgXVweImPhnlwdIGLh313dHiEiYR9eHZ7hIeGgnlyeYmPh3tvcIGRjYBybXqMkYZ6cXOBjY6Ee3R2hJCPhndud4yWj31ra3+Wl4RvaXaNmIp3b3SBjo6Cd3V4gYmJhH53dHyKj4p+cG+AlJaFcmt1ipSKdWpteoqMgHVzeICIioJ8e3h8h46KgHd0fpCVjHxxcYGTk4Z4cXaGkIuAeHJ0gY+QhnZrboOXloNvZ3SMmpB6amp6kJaIdm5xe4qOh310bnWHk5CAbmZzjpqQeGZmepWciW5lbYGVmId1bnF+jZKIem5qdYyZkHtoZHWRoZV4Y2J3lqORcmFlfpyjjnJla4CYnYpyZ2p8k5uLc2hse5GajnpsaXaLmpJ4aGp4kJuQeWtreIyak35uaXGGmJeEbmhziZ2dhWxpc4ibm4VuaHSImZqGcGpyg5KWiHNtdH6Jkox7bm93hpOSfm5wfIaNjH91eoGAgYeJg317eXqFi4R7eHh5gYiHgX54cneFi4d+dG90go+Nf3Z0doCLioJ/fXd2fYeMi4FzbHSGlJKDcmhwhZWXiXRqbH6Tl4t7cGtyhpaXi3hoan6Wn5N4ZGN0jJqTfGllcIGTmot1bG96i5eSfnBveIWPkIV4dnuBg4aHhYF+enR3goyLgHJrcYSUkoJzc3uEiomCfX6Af32AiIyIgnp1eIKKjYh+dHJ4hpGRhHZvdYaQjoJ3dnyCgn6AgoODfnh3foSHhoB5dHR9h4uHfXRyd4GMj4R0bnaDjIp+eHqAhIWAenuAg4WEfnd1fIWLioB1cnqEi4yFenZ4foOFgn99fHt8foCBgoKCgXx5fIKEhYJ7d3p+goOCgH5+foCCgYCAgIOAfnx8gIOEhoN/foGFhoN9e36DhoR+en2ChYSAfX2Ag4KBgYKDgoB+gIKCgoGAgYKAfn6ChYR9en2ChoeBenuAhYSAfX6Ag4SAfX2AgoKCgH9+fX2Ag4KBfXp7goaDgH19gIKBfoCBgHt6fIGDgn58fYGCgH59gIKBfXt+gYKCfXl6foKEgXx5e4KGhoF8e4CEhIKAfXt+gYGChISBfXx+hIeFfnp8gYaHhYB9gIKDg4KBgYB+foCEhIB8enyEiod+eHqBiIiCenh+g4SBfnx8fXx7fICAfXp7foSGgXx8foKEgn59foGCgoGBgYKAgICBgoSEgn5+goeKhHx4eYCHiIN7eHqCiod+eHl9goWFgHt7fYCEhYJ7dniAhoWAenh6goeEfnt6fIKGhH15en2DhoJ9e3x+gYOCgH59fICCgYKAfHx9goSCgX17foKEgn56fICCgHx8fX6AgYB+fn5+fn6AgoJ+e3yAg4WEgH5+gYOCgH5+gH9+fn6ChIB6eHuAhoZ+eXp/hIeEfn2Ag4KAgYWGhIGAf4KFhoOBfnx+goSFhIB+fYCEhoSCgH6AgoSDgoCAgIGCg4OBfn1+gYKAfnt8foGBgH98fH+CgoB8enyAgoKAfXt+g4OBfnyAgoJ+fHyAg4N+ent+goOCf319fn+ChIF9e3x/gIGAgIB+fX2AgoWFgHp7foKDgn59fYGDhIOCgYKFhIKCgYCBg4OCgH2AhIaEgHx7foKEhH56e36ChISAfHyAg4WDgoKAfoCCgX99e3h5fICAfnt8f4KBgH9+gYSEgH5/goSFhoJ9fH+DhoV/enp+hIiHg318foGDhIJ/fX2AhoiFf3p4fIOGg3p0dn+GhoB5dnmAhIOAfn59foGEhIJ+fHx8gISFgn57fH6DhIJ+fHx/goSEgH19fYCBgICAgICAfHx+goSCfnx8foGDhIF+fH6BgoSCfnx8gISEgX58fH+CgoB+fH5/f4CAgIB/fH2AgoOAfXx+gIKCgH19foCDhYOAfn6Bg4SDgH5+gYOFgn59foGCg4OAfn5/goKCg4GAgIGChIJ/fH2Ag4WEgHp6foKGhHx4eX2DhIN/enp+goODgH18gIKBgYGAfn59foGBgH59fX5+foCCgn58fX6Bg4F9fH5+fn6CgoB+foCDhIF+foCCgoF+fn+BgoKAf4CBgYB/gIB/gIODhIKAfoCChISBfn1+gYODgn9+foCCgoB+fH5/gIB+fHyAgoOCfn1/gYOEgn5+gIGBgYGAfHx8fYCAfn18fICCgoF/foCBgoJ/fH2BhYaEgX9+gYWGg357fICEhoSBfn2AhIWFgn58fYCDhIF+fn6ChIOAf39+gYSCgH59foGCgH58fn+BgX98fICAgYB+fn5+f39+fn5+fX5+fn1+fn5/gH58fYB/fn18foGDgoCAgYKDg4B+fX2AgYCAgH9+foCBf4CBgICAgICBgICBgX9+fn+AgYGAfn2AgYKBf35+gIOCgYGAgoKCgoF+gYKCgoSAgYGBgoKDgYB+foB/f35/gICBgYCBgYGBgYGCgoKAgICChISCgH6AgoKCgH5/gIGBgYCBgH5/gYKAfn6AgIGAfX1/gYODgH18fICCgn58fHx9foCAfn18foB+foB+fn6AgH5/fn6AgoGAfoCAgIB+fn1+gIGBgH19foKEgn99foCChISDgH6AgYGCgX5+gICAgYF+fX1+gICCgoGAgIKDg4KDgoKDhISBf4CBg4WEgn5+gIKDg4B9fHt8fn6Afnt7foGCgoB+fYCCgoKCgIGBgoGBgIKCgoKCgoKCgYCCg4OEg4F/foCCgYGAgICBgYF+fn19fX1+fX19fYCCgoGBgH5+fn5/fn18foGBgH17e36Cg4F+fH6Ag4KAfX1/gYKCgYCAf4CAgICBgH9+f4CAgoKAfn6BgoKBgICAgIGAfn19fn19fHx9f4B+f39+fn6AgH59fXx9gIB+fn9/gICBgoKCgoGBgYKCgoKBgICAgYGBgICAgICBgYCBgoKBgICAgoKCgoGBgYKCgYGCg4KBgICAgYCBgoGAgIGCgoGAgICBg4KAgICBgoKCgH5+foCAgH5+foCCgYCAgH9/gYGAf358fH6Afn18foAA"
</script>
You can write a service using $q.defer()
.
app.service('service', ['$q', function($q){
this.play = function play(sound) {
var deferred = $q.defer();
sound.play();
sound.onended = function(e) {
deferred.resolve(e);
}
return deferred.promise;
}
}]);
You can just call the service and expecting the promise return.
service.play(sound).then(function(e){});
Full plunker sample - http://plnkr.co/edit/FJYjj4ehslqZQZmYyL1I?p=preview
There is an 'ended' event that is emitted when the audio has finished playing. Source
this.play = function(trackName) {
return new Promise(function(resolve, reject) {
var audio = _sounds[trackName].audio;
audio.addEventListener('ended', resolve);
audio.play();
});
};