|
8 | 8 | 6. [Objects](#objects)
|
9 | 9 | 7. [ES6](#es6)
|
10 | 10 | 8. [Class](#class)
|
| 11 | +9. [Promises](#promises) |
11 | 12 |
|
12 | 13 | ## Variable scope
|
13 | 14 |
|
@@ -856,3 +857,133 @@ function instantiate(TheClass, args) {
|
856 | 857 | return Reflect.construct(TheClass, args);
|
857 | 858 | }
|
858 | 859 | ```
|
| 860 | + |
| 861 | +## Promises |
| 862 | +The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. |
| 863 | + |
| 864 | +A **Promise** is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future. |
| 865 | + |
| 866 | +A Promise is in one of these states: |
| 867 | +* pending: initial state, neither fulfilled nor rejected. |
| 868 | +* fulfilled: meaning that the operation completed successfully. |
| 869 | +* rejected: meaning that the operation failed. |
| 870 | + |
| 871 | +### Creating Promise using Constructor |
| 872 | +A Promise object is created using the `new` keyword and its constructor. This constructor takes as its argument a function, called the "executor function". This function should take two functions as parameters. The first of these functions (resolve) is called when the asynchronous task completes successfully and returns the results of the task as a value. The second (reject) is called when the task fails, and returns the reason for failure, which is typically an error object. |
| 873 | +``` |
| 874 | +var promise1 = new Promise(function(resolve, reject) { |
| 875 | + setTimeout(function() { |
| 876 | + resolve('foo'); |
| 877 | + }, 300); |
| 878 | +}); |
| 879 | + |
| 880 | +promise1.then(function(value) { |
| 881 | + console.log(value); |
| 882 | + // expected output: "foo" |
| 883 | +}); |
| 884 | + |
| 885 | +console.log(promise1); |
| 886 | +// expected output: [object Promise] |
| 887 | +``` |
| 888 | +### Promising HTTP requests: |
| 889 | +The following is a Promise-based function that performs an HTTP GET via the event-based `XMLHttpRequest` API: |
| 890 | +``` |
| 891 | +function httpGetRequest(url) { |
| 892 | + return new Promise( |
| 893 | + function (resolve, reject) { |
| 894 | + const request = new XMLHttpRequest(); |
| 895 | + request.onload = function () { |
| 896 | + if (this.status === 200) { |
| 897 | + // Success |
| 898 | + resolve(this.response); |
| 899 | + } else { |
| 900 | + // Something went wrong (404 etc.) |
| 901 | + reject(new Error(this.statusText)); |
| 902 | + } |
| 903 | + }; |
| 904 | + request.onerror = function () { |
| 905 | + reject(new Error( |
| 906 | + 'XMLHttpRequest Error: '+this.statusText)); |
| 907 | + }; |
| 908 | + request.open('GET', url); |
| 909 | + request.send(); |
| 910 | + }); |
| 911 | +} |
| 912 | +``` |
| 913 | +To use this: |
| 914 | +``` |
| 915 | +httpGetRequest('http://example.com/file.txt') |
| 916 | +.then( |
| 917 | + function (value) { |
| 918 | + console.log('Contents: ' + value); |
| 919 | + }, |
| 920 | + function (reason) { |
| 921 | + console.error('Something went wrong', reason); |
| 922 | + }); |
| 923 | +``` |
| 924 | +### Chaining Promises |
| 925 | +A promise can be chained by returning another promise. The flat version looks like this: |
| 926 | +``` |
| 927 | +asyncFunc1() |
| 928 | +.then(function (value1) { |
| 929 | + return asyncFunc2(); |
| 930 | +}) |
| 931 | +.then(function (value2) { |
| 932 | + ··· |
| 933 | +}) |
| 934 | +``` |
| 935 | +### Chaining and errors |
| 936 | +There can be one or more `then()` method calls that don’t have error handlers. Then the error is passed on until there is an error handler. |
| 937 | +``` |
| 938 | +asyncFunc1() |
| 939 | +.then(asyncFunc2) |
| 940 | +.then(asyncFunc3) |
| 941 | +.catch(function (reason) { |
| 942 | + // Something went wrong above |
| 943 | +}); |
| 944 | +``` |
| 945 | +### Forking and joining via `Promise.all()` |
| 946 | +`Promise.all(iterable)` takes an iterable promises and returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects. |
| 947 | +``` |
| 948 | +var promise1 = Promise.resolve(3); |
| 949 | +var promise2 = 42; |
| 950 | +var promise3 = new Promise(function(resolve, reject) { |
| 951 | + setTimeout(resolve, 100, 'foo'); |
| 952 | +}); |
| 953 | + |
| 954 | +Promise.all([promise1, promise2, promise3]).then(function(values) { |
| 955 | + console.log(values); |
| 956 | +}); |
| 957 | +// expected output: Array [3, 42, "foo"] |
| 958 | +``` |
| 959 | +### Timing out via `Promise.race()` |
| 960 | +The `Promise.race(iterable)` method returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects, with the value or reason from that promise. |
| 961 | +``` |
| 962 | +var promise1 = new Promise(function(resolve, reject) { |
| 963 | + setTimeout(resolve, 500, 'one'); |
| 964 | +}); |
| 965 | + |
| 966 | +var promise2 = new Promise(function(resolve, reject) { |
| 967 | + setTimeout(resolve, 100, 'two'); |
| 968 | +}); |
| 969 | + |
| 970 | +Promise.race([promise1, promise2]).then(function(value) { |
| 971 | + console.log(value); |
| 972 | + // Both resolve, but promise2 is faster |
| 973 | +}); |
| 974 | +// expected output: "two" |
| 975 | +``` |
| 976 | +### Finally `finally` |
| 977 | +Sometimes you want to perform an action independently of whether an error happened or not. For example, to clean up after you are done with a resource. That’s what the Promise method `finally()` is for, which works much like the finally clause in exception handling. Its callback receives no arguments, but is notified of either a resolution or a rejection. |
| 978 | +``` |
| 979 | +createResource(···) |
| 980 | +.then(function (value1) { |
| 981 | + // Use resource |
| 982 | +}) |
| 983 | +.then(function (value2) { |
| 984 | + // Use resource |
| 985 | +}) |
| 986 | +.finally(function () { |
| 987 | + // Clean up |
| 988 | +}); |
| 989 | +``` |
0 commit comments