Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

User talk:Poltawski/Javascript promises: Difference between revisions

From MoodleDocs
Line 14: Line 14:
==== Correct ====
==== Correct ====
<code javascript>
<code javascript>
// Good:
str.get_strings(stringRequests).then(function(title) {
str.get_strings(stringRequests).then(function(title) {
     return templates.renderPix(image, 'core', title);
     return templates.renderPix(image, 'core', title);

Revision as of 13:39, 12 June 2017

Promises

Promises are used extensively in modern Moodle Javascript APIs to handle asynchronous situations. It is unfortunately common to misunderstand how they operate and introduce bugs which only expose themselves in asynchronous edge cases (see article we have a problem with promises). To encourage promise usage to be more understandable, consistent and avoid edge case bugs, we have adopted best practices suggested by Nolan Lawson and verified by eslint-plugin-promise.

Always return or throw

When writing promises they must:

  • return another promise, or
  • return a synchronous value (or undefined), or
  • throw a synchronous error

Correct

str.get_strings(stringRequests).then(function(title) {

   return templates.renderPix(image, 'core', title);

}).then(function(pixhtml) {

   $('#selector').html(pixhtml);
   makeUIVisible();
   return;

});

Incorrect

str.get_strings(stringRequests).then(function(title) {

   templates.renderPix(image, 'core', title).function(pixhtml) {
       $('#selector').html(pixhtml);
   });

}).then(function() {

   // Wrong because renderPix() has not guaranted to be resolved here.
   makeUIVisible();

});

Do not nest

The great advantage of promises is keeping async code linear rather than nested in callback hell and handling errors in one place, by nesting promises these advantages are lost.

Correct

renderPromise().then(function (html) {

   return Str.get_string('competencypicker', 'tool_lp');

}).then(function(title) {

   self._popup = new Dialogue(title, html);

});

Incorrect

return renderPromise().then(function (html) { return Str.get_string('competencypicker', 'tool_lp').then(function(title) { self._popup = new Dialogue(title, html); }); });