User talk:Poltawski/Javascript promises: Difference between revisions
No edit summary |
|||
Line 12: | Line 12: | ||
* throw a synchronous error | * throw a synchronous error | ||
==== Correct ==== | |||
<code> | <code javascript> | ||
// Good: | // Good: | ||
str.get_strings(stringRequests).then(function(title) { | str.get_strings(stringRequests).then(function(title) { | ||
Line 22: | Line 22: | ||
return; | return; | ||
}); | }); | ||
</code> | |||
==== Incorrect ==== | |||
<code javascript> | |||
str.get_strings(stringRequests).then(function(title) { | str.get_strings(stringRequests).then(function(title) { | ||
templates.renderPix(image, 'core', title).function(pixhtml) { | templates.renderPix(image, 'core', title).function(pixhtml) { | ||
Line 39: | Line 40: | ||
The great advantage of promises is keeping async code linear rather than nested in <i>callback hell</i> and handling errors in one place, by nesting promises these advantages are lost. | The great advantage of promises is keeping async code linear rather than nested in <i>callback hell</i> and handling errors in one place, by nesting promises these advantages are lost. | ||
<code> | ==== Correct ==== | ||
<code javascript> | |||
renderPromise().then(function (html) { | renderPromise().then(function (html) { | ||
return Str.get_string('competencypicker', 'tool_lp'); | return Str.get_string('competencypicker', 'tool_lp'); | ||
Line 47: | Line 47: | ||
self._popup = new Dialogue(title, html); | self._popup = new Dialogue(title, html); | ||
}); | }); | ||
</code> | |||
==== Incorrect ==== | |||
<code javascript> | |||
return renderPromise().then(function (html) { | return renderPromise().then(function (html) { | ||
return Str.get_string('competencypicker', 'tool_lp').then(function(title) { | return Str.get_string('competencypicker', 'tool_lp').then(function(title) { |
Revision as of 13:37, 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
// Good:
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);
});
});