Promise in js
The real problem with callback functions is that they deprive us of the ability to use the keywords return and throw. Promise solves all this well.
In June 2015, The Official Edition of ECMAScript 6 It was finally released.
ECMAScript is the international standard of JavaScript language, and JavaScript is the implementation of ECMAScript. The goal of ES6 is to enable JavaScript language to be used to write large and complex applications and to become an enterprise-level development language.
concept
ES6 natively provides Promise objects.
The so-called Promise is an object used to deliver messages for asynchronous operations. It represents an event (usually an asynchronous operation) that will know the result in the future, and it provides a unified API for further processing.
Promise objects have the following two characteristics.
(1) The state of the object is not affected by the outside world. Promise objects represent an asynchronous operation in three states: Pending (in progress), Resolved (completed, also known as Fulfilled) and Rejected (failed). Only the result of an asynchronous operation can determine which state it is currently, and no other operation can change that state. This is also the origin of the name Promise, which means "commitment" in English, meaning that other means can not be changed.
(2) Once the state changes, it will not change again, and this result can be obtained at any time. There are only two possibilities for the state change of Promise objects: from Pending to Resolved and from Pending to Rejected. As long as these two situations occur, the state will be solidified, will not change any more, will always maintain this result. Even if the change has happened, you can immediately get the result by adding a callback function to the Promise object. This is completely different from Event, which is characterized by the fact that if you miss it and listen on it, you will not get results.
With Promise objects, asynchronous operations can be expressed as synchronous operations, avoiding nested callback functions. In addition, Promise objects provide a unified interface, making it easier to control asynchronous operations.
Promise also has some drawbacks. First, Promise cannot be cancelled. Once it is newly built, it will be executed immediately and cannot be cancelled halfway. Secondly, if the callback function is not set, the errors thrown inside Promise will not be reflected outside. Thirdly, when in the Pending state, it is impossible to know which stage of the current progress is (just beginning or about to be completed).
var promise = new Promise(function(resolve, reject) {
if (/* Successful asynchronous operation */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(value) {
// failure
});
The Promise constructor accepts a function as a parameter. The two parameters of the function are resolve method and reject method, respectively.
If the asynchronous operation succeeds, the state of the Promise object is changed from "pending" to "successful" using the resolve method.
If the asynchronous operation fails, the state of the Promise object is changed from "pending" to "rejected" using reject method.
Basic api
- Promise.resolve()
- Promise.reject()
- Promise.prototype.then()
- Promise.prototype.catch()
-
Promise.all()// All Completions
var p = Promise.all([p1,p2,p3]);
- Promise.race()// race, just finish one.
Advanced
The magic of promises is to give us back and throw. Each Promise provides a then() function and a catch(), which is actually then(null,...) function.
somePromise().then(functoin(){
// do something
});
We can do three things.
1. return another promise 2. return a synchronized value (or undefined) 3. throw a synchronization exception `throw new Eror(');`
1. Encapsulating synchronous and asynchronous code
``` new Promise(function (resolve, reject) { resolve(someValue); }); ``` //finish writing sth. ``` Promise.resolve(someValue); ```
2. Capturing Synchronization Anomalies
new Promise(function (resolve, reject) {
throw new Error('Tragedy, come out again bug δΊ†');
}).catch(function(err){
console.log(err);
});
If it is synchronous code, it can be written as
Promise.reject(new Error("What the hell?"));
3. Multiple exception capture, more accurate capture
somePromise.then(function() {
return a.b.c.d();
}).catch(TypeError, function(e) {
//If a is defined, will end up here because
//it is a type error to reference property of undefined
}).catch(ReferenceError, function(e) {
//Will end up here if a wasn't defined at all
}).catch(function(e) {
//Generic catch-the rest, error wasn't TypeError nor
//ReferenceError
});
4. Get the return values of two Promise s
1. The way to call sequentially 2. Setting higher scopes 3. spread
5. finally
It will be executed in any case, usually after catch
6. bind
somethingAsync().bind({})
.spread(function (aValue, bValue) {
this.aValue = aValue;
this.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return this.aValue + this.bValue + cValue;
});
Or you can do the same.
var scope = {};
somethingAsync()
.spread(function (aValue, bValue) {
scope.aValue = aValue;
scope.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return scope.aValue + scope.bValue + cValue;
});
However, there are many differences.
- You have to declare that there is a risk of wasting resources and memory leaks.
- Can't be used in the context of an expression
- Lower efficiency
7. all. Very useful for processing a Roise list with uniform dynamic size
8. join. Very suitable for handling multiple separated Promise s
```
var join = Promise.join;
join(getPictures(), getComments(), getTweets(),
function(pictures, comments, tweets) {
console.log("in total: " + pictures.length + comments.length + tweets.length);
});
```
9. props. Processing a map collection of promise s. There is only one failure, and all execution is over.
```
Promise.props({
pictures: getPictures(),
comments: getComments(),
tweets: getTweets()
}).then(function(result) {
console.log(result.tweets, result.pictures, result.comments);
});
```
10. any ,some,race
```
Promise.some([
ping("ns1.example.com"),
ping("ns2.example.com"),
ping("ns3.example.com"),
ping("ns4.example.com")
], 2).spread(function(first, second) {
console.log(first, second);
}).catch(AggregateError, function(err) {
err.forEach(function(e) {
console.error(e.stack);
});
});;
``` It's possible that there are more promises that fail, leading to the fact that promise will never fulfill.
11. .map(Function mapper [, Object options])
Used to process an array, or promise array,
Option: concurrency and discovery
map(..., {concurrency: 1});
Following is no limit on the number of concurrent, read file information
var Promise = require("bluebird");
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
var concurrency = parseFloat(process.argv[2] || "Infinity");
var fileNames = ["file1.json", "file2.json"];
Promise.map(fileNames, function(fileName) {
return fs.readFileAsync(fileName)
.then(JSON.parse)
.catch(SyntaxError, function(e) {
e.fileName = fileName;
throw e;
})
}, {concurrency: concurrency}).then(function(parsedJSONs) {
console.log(parsedJSONs);
}).catch(SyntaxError, function(e) {
console.log("Invalid JSON in file " + e.fileName + ": " + e.message);
});
Result
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js 1
reading files 35ms
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js Infinity
reading files: 9ms
11. .reduce(Function reducer [, dynamic initialValue]) -> Promise
Promise.reduce(["file1.txt", "file2.txt", "file3.txt"], function(total, fileName) {
return fs.readFileAsync(fileName, "utf8").then(function(contents) {
return total + parseInt(contents, 10);
});
}, 0).then(function(total) {
//Total is 30
});
12. Time
- .delay(int ms) -> Promise
- .timeout(int ms [, String message]) -> Promise
Implementation of Promise
ASYNC
Like Promise and Generator functions, async functions are used to replace callback functions and solve asynchronous operations. It is essentially a grammatical sugar of the Generator function. The async function does not belong to ES6, but is included in ES7.