javascript - setTimeout returns error with Uncaught TypeError: Illegal invocation in AudioContext in Chrome - Stack Overflow

In Chrome I first create a continuous tone with the AudioContext:var audioCtx = new (window.AudioContex

In Chrome I first create a continuous tone with the AudioContext:

var audioCtx = new (window.AudioContext || window.webkitAudioContext);

var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

oscillator.start();

Now I want to stop it after a few milliseconds. So I do this:

setTimeout(oscillator.stop, 500)

This returns the error Uncaught TypeError: Illegal invocation.

However if I do;

setTimeout(function(){oscillator.stop()}, 500)

it works fine.

I would like to now why the first one doesn't work and returns an error. It seems like the straightforward way to do this.

In Chrome I first create a continuous tone with the AudioContext:

var audioCtx = new (window.AudioContext || window.webkitAudioContext);

var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

oscillator.start();

Now I want to stop it after a few milliseconds. So I do this:

setTimeout(oscillator.stop, 500)

This returns the error Uncaught TypeError: Illegal invocation.

However if I do;

setTimeout(function(){oscillator.stop()}, 500)

it works fine.

I would like to now why the first one doesn't work and returns an error. It seems like the straightforward way to do this.

Share Improve this question asked Apr 15, 2015 at 2:55 HoushalterHoushalter 2,8181 gold badge19 silver badges21 bronze badges 4
  • 1 setTimeout(oscillator.stop.bind(oscillator), 500) – elclanrs Commented Apr 15, 2015 at 2:59
  • Thanks, that works. But why does it work, and why doesn't the simple way work? – Houshalter Commented Apr 15, 2015 at 3:07
  • This doesn't really answer your question, but another way to achieve the same effect would be to call stop() directly with the number of seconds to wait as the parameter so in your case oscillator.stop(0.5). Here is a working fiddle – HJ05 Commented Apr 15, 2015 at 3:09
  • I tried that first actually but it seems to be buggy in Chrome. It seems to measure the time since AudioContext was created, rather than the time since it was called. E.g. this: jsfiddle/j3q3npkc – Houshalter Commented Apr 15, 2015 at 3:29
Add a ment  | 

1 Answer 1

Reset to default 9

Your original code doesn't work because the stop function is passed to setTimeout without any context - it does not know which object it is supposed to act on. If you invoke it like this:

oscillator.stop();

Then within stop, the special variable this is set to the object pointed to by oscillator. But if you refer to it like this:

var x = oscillator.stop;

The function is not actually invoked. Rather, a reference to the function is simply extracted from oscillator and stored elsewhere. The function does not remember where it came from, and could be stored in many different variables or object properties at the same time. For example:

var x = {};
x.foo = oscillator.stop;
x.foo();

The last line calls stop with a context of x (this is set to x) rather than oscillator. (The function's body will cause errors since stop makes assumptions about what its context looks like, but the call itself is legal.) Alternatively, if you do this:

var foo = oscillator.stop;
foo();

Then stop will be called with only a default context. In strict mode, this will be set to undefined, and in non-strict mode, this will be set to window.

When you do this:

setTimeout(function(){oscillator.stop()}, 500)

The anonymous function invokes stop with the proper context. If, as suggested by @elclanrs in ments, you do this:

setTimeout(oscillator.stop.bind(oscillator), 500)

It is effectively the same thing: an anonymous function is created that calls stop with a context of oscillator.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744400811a4572375.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信