17849

webglcontextcreationerror event: is it triggered synchronously?

Question:

Is the <a href="https://developer.mozilla.org/en-US/docs/Web/Events/webglcontextcreationerror" rel="nofollow">webglcontextcreationerror event</a> triggered synchronously or asynchronously? For example does

canvas.addEventListener("webglcontextcreationerror", function() { console.log("Error"); }); var context = canvas.getContext("webgl"); console.log("After creation");

in the case of error output

"After creation" "Error"

or

"Error" "After creation"

?

I am unsure how to force this event to find out the answer myself.

Answer1:

<strong>NB</strong> : This is not a per spec answer, but only from a single UA test, so it may be wrong, or at least true only to this UA, a.k.a Chrome.

<hr />

In chrome, to force the error event, you can first request a 2dContext then a webgl one.

This way we can see that this UA does treat the event as an synchronous one.<br /><sub> I just learn about these right-now...</sub>

<pre class="snippet-code-js lang-js prettyprint-override">var canvas = document.createElement('canvas') canvas.addEventListener("webglcontextcreationerror", function() { snippet.log("Error"); }); canvas.getContext('2d') canvas.getContext("webgl"); snippet.log("After creation"); <pre class="snippet-code-html lang-html prettyprint-override"><!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Answer2:

So one question is why do you care the order? getContext returns null on failure so if you want to know if it failed then you're done. webglcontextcreationerror's only point is for you to get the reason why it failed since getContext has no way to do that. So, you could structure your code such that it doesn't matter whether it's sync or async

<pre class="snippet-code-js lang-js prettyprint-override">var canvas = document.createElement('canvas') function doSomethingWithStatusMessage(e) { log("context creation error: "+ e.statusMessage); } canvas.addEventListener("webglcontextcreationerror", doSomethingWithStatusMessage); log("2d: " + canvas.getContext('2d')); log("webgl: " + canvas.getContext("webgl")); log("after creation"); function log(msg, color) { var div = document.createElement("pre"); div.appendChild(document.createTextNode(msg)); document.body.appendChild(div); }

doSomethingWithStatus message could do anything you want. Assume based on getContext you display a dialog.

if (!canvas.getContext("webgl")) { g_dialog = new Dialog("can't create context", g_reason); }

Then you might have code like

var g_reason = "unknown"; var g_dialog; function doSomethingWithStatusMessage(e) { if (g_dialog) { g_dialog.updateReason(e.statusMessage); } else { g_reason = g.statusMessage; } } function Dialog(msg, reason) { var div = document.createElement("div"); div.appendChild(document.createTextNode(msg)); var reasonNode = document.createTextNode(""); div.appendChild(reasonNode); updateReason(reason); function updateReason(reason) { reasonNode.nodeValue = reason; } this.updateReason = updateReason; }

<pre class="snippet-code-js lang-js prettyprint-override">var g_reason = "unknown"; var g_dialog; function doSomethingWithStatusMessage(e) { if (g_dialog) { g_dialog.updateReason(e.statusMessage); } else { g_reason = e.statusMessage; } } var canvas = document.createElement('canvas') canvas.addEventListener("webglcontextcreationerror", doSomethingWithStatusMessage); log("2d: " + canvas.getContext('2d')); var gl = canvas.getContext("webgl"); log("webgl: " + gl); log("after creation"); if (!gl) { new Dialog("could not create WebGL context: ", g_reason); } function log(msg, color) { var div = document.createElement("pre"); div.appendChild(document.createTextNode(msg)); document.body.appendChild(div); } function Dialog(msg, reason) { var outer = document.createElement("div"); outer.className = "dialog"; var div = document.createElement("div"); div.appendChild(document.createTextNode(msg)); var reasonNode = document.createTextNode(""); div.appendChild(reasonNode); outer.appendChild(div); updateReason(reason); document.body.appendChild(outer); outer.addEventListener('click', close); function updateReason(reason) { reasonNode.nodeValue = reason; } function close() { document.body.removeChild(outer); outer.removeEventListener('click', close); } this.close = close; this.updateReason = updateReason; } <pre class="snippet-code-css lang-css prettyprint-override">.dialog { position: absolute; z-index: 2; background: rgba(0,0,0,0.8); color: red; left: 0; top: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-content: center; align-items: center; }

If instead you wanted to report the error to a server for example then just trigger it a few moments later to give the async message a chance to arrive.

if (!canvas.getContext("webgl")) { // give a moment for the async message to arrive setTimeout(uploadReason, 1000); }

The rest would just be

var g_reason = "unknown"; function doSomethingWithStatusMessage(e) { g_reason = e.statusMessage; } function uploadReason() { .. XHR g_reason to server .. }

Note: I <a href="https://github.com/KhronosGroup/WebGL/issues/1603" rel="nofollow">file a bug on this part of the spec</a> so you can follow up if you'd like.

Recommend

  • Using RestKit to perform a synchronous request
  • $.getJson> $.each returns undefined
  • ASP.NET asynchronous page user interface
  • is asynchronicity a constant for a) functions or b) lines of code?
  • Gemfire Persistent Overflow
  • What does 'sintr' mean (in Ganglia)?
  • R: How to Parallelize multi-panel plotting with lattice in R 3.2.1?
  • disable downloading of image from a html page
  • iPhone simulator not found
  • Waiting for an Asynchronous method in NodeJS
  • Should I unit test concurrency?
  • google earth fetchKml timeout
  • JavaFX/SWT WebView synchronous loadcontent()
  • In metro, what's the difference between FolderInformation and StorageFolder
  • Retrieve file size from web server
  • Elixir GenServer parallel handle_call
  • jinja2 template not found and internal server error
  • How secure are apple APNS push notifications?
  • Why does the font in these TD elements render at different sizes?
  • How to view images from protected folder with php?
  • Display images in Django
  • Jquery UI tool tip close icon
  • Javascript simulate pressing enter in input box
  • Resize panoramic image to fixed size
  • Shallow update not allowed (git > 1.9)
  • Importing jscolor library in angular 2
  • How do I rollback to a specific git commit
  • bootstrap to use multiple ng-app
  • How to get icons for entities from eclipse?
  • A cron job substitute?
  • Revoking OAuth Access Token Results in 404 Not Found
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • How do I configure my settings file to work with unit tests?
  • Turn off referential integrity in Derby? is it possible?
  • Is it possible to post an object from jquery to bottle.py?
  • JaxB to read class hierarchy
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?