Do we need Promise?
Look at the code below
$.ajax(url1, function(data1){
// do something...
$.ajax(url2, function(data2){
// do something...
$.ajax(url3, function(data3){
// do something...
done(data3); // Return data})}); });Copy the code
- Easy to create when there are no asynchronous objects
Callback hell
The problem is that layers of nested code are extremely inconvenient to maintain and even harder to read - Asynchronous objects have been around since the days of Jquery
$.Deferred
Like the ones we use$.ajax
It is code modified by an asynchronous object using an asynchronous object
Asynchronously parallel requests and processes them after the results are all returned
$.when($.ajax({
url: 'https://www.easy-mock.com/mock/5937664f91470c0ac1073a73/example/test'
}), $.ajax({
url: 'https://www.easy-mock.com/mock/5937664f91470c0ac1073a73/example/test'
})).done((p1, p2) = > {
console.log(p1, p2)
})
Copy the code
let b = $.Deferred()
function a(dtd) {
setTimeout(function () {
console.log(1234)
dtd.resolve('b is done')}, 400)return dtd
}
$.when(a(b)).done(res => {
console.log(res)
})
Copy the code
It looks like an asynchronous object is actually a very convenient thing to use because it allows you to do some asynchronous code that you can write synchronously.
What is Promise?
Promise implementation specification Promise A+
- Is a new feature of ES6 that has been included in the official specification of ES6
- Promise objects can be thought of as asynchronous operations that are performed once, and they can be used to organize code in a chain of calls. Make the code more intuitive. That is, with the Promise object, asynchronous operations can be expressed as a flow of synchronous operations, eliminating layers of nested callback functions
- Fix callback hell
- Easy to maintain
- Resolve synchronization asynchronously by returning results in order
- The chain-call (JQ implementation relies on returning this) Promise cannot return this Promise. The chain-call dependency implementation returns a new Promise
- If either a successful or a failed callback in a THEN returns a value, success in the next THEN returns a failure in the next THEN
- If the first promise returns a normal value, it goes straight to the next THEN successful callback. If the first promise returns a promise, the result of the returned promise execution needs to be passed to the next THEN
- resolvePromise
- Determine if x is a promise. If x is an object and x’s then method is a function, we assume it is a promise
- Promise values pass through empty then directly
- The Promise specification requires that all onFufiled and onRejected be executed asynchronously
This is a big pity, which is a pity. Graph LR pendding -->Rejected --> this is a big pityCopy the code
Basic usage
Much like $.Deffered, it relies on returning an asynchronous object to solve callback hell
function test() {
return new Promise((res, rej) = > {
setTimeout(function () {
console.log('Delayed execution')
res('done')},2000)
})
}
test().then(function (res) {
console.log(res)
})
Copy the code
Make a simple Promise
From the code above we can see that a Promise has several characteristics
- The argument is a function that contains two methods: resolve and reject
- The returned instance contains then methods and the call timing of the THEN method is related to the execution of resolve and Reject
- The return parameters of resolve and reject are passed directly to the THEN method
Initialize a Promise
function Promise(executor) {
/ / executor actuators
this.status = 'pending'
this.reason = null
this.data = null
function resolve() {}function reject() {
}
executor(resolve, reject)
}
Promise.prototype.then = function (res, rej) {}Copy the code
Added handling of incoming data when calling resolve and Reject
function Promise(executor) {
/ / executor actuators
this.status = 'pending'
this.reason = null
this.data = null
const _this = this;
function resolve(data) {
if (_this.status == 'pending') {
_this.data = data
_this.status = 'onFulfilled'}}function reject(e) {
if (_this.status == 'pending') {
_this.reason = e
_this.status = 'rejected'
}
}
executor(resolve, reject)
}
Promise.prototype.then = function (res, rej) {}Copy the code
The Promise state is modified at execution time and the timing of the call to the THEN function is handled
function Promise(executor) {
/ / executor actuators
this.status = 'pending'
this.reason = null
this.data = null
const _this = this;
function resolve(data) {
if (_this.status == 'pending') {
_this.data = data
_this.status = 'onFulfilled'}}function reject(e) {
if (_this.status == 'pending') {
_this.reason = e
_this.status = 'rejected'
}
}
executor(resolve, reject)
}
Promise.prototype.then = function (res, rej) {
const _this = this
if(_this.status=='onFulfilled'){
res(_this.data)
return
}
if(_this.status=='rejected'){
res(_this.reason)
}
}
Copy the code
Take a test walk
function test() {
return new Promise(function (resolve, reject) {
console.log('promise is running')
resolve('2')
})
}
test().then((res) = > {
console.log(res)
}, (e) => {
console.log(e, e)
})
Copy the code
OK synchronization code passed
The asynchronous invocation is then implemented
- Added two new attributes onControllLedList onRejectedList to be invoked during asynchronous execution
function Promise(executor) {
/ / executor actuators
this.status = 'pending'
this.reason = null
this.data = null
this.onFulFilledList = []
this.onRejectedList = []
const _this = this;
function resolve(data) {
if (_this.status == 'pending') {
_this.data = data
_this.status = 'onFulfilled'}}function reject(e) {
if (_this.status == 'pending') {
_this.reason = e
_this.status = 'rejected'
}
}
executor(resolve, reject)
}
Promise.prototype.then = function (res, rej) {
const _this = this
if (_this.status == 'onFulfilled') {
res(_this.data)
return
}
if (_this.status == 'rejected') {
rej(_this.reason)
}
}
Copy the code
The success and failure functions of asynchronous calls are stored in queues to facilitate calls and the callback queue methods are directly executed when called
function Promise(executor) {
/ / executor actuators
this.status = 'pending'
this.reason = null
this.data = null
this.onFulFilledList = []
this.onRejectedList = []
const _this = this;
function resolve(data) {
if (_this.status == 'pending') {
_this.data = data
_this.status = 'onFulfilled'
_this.onFulFilledList.forEach(element= >{ element(_this.data) }); }}function reject(e) {
if (_this.status == 'pending') {
_this.reason = e
_this.status = 'rejected'
_this.onRejectedList.forEach(element= > {
element(_this.reason)
});
}
}
executor(resolve, reject)
}
Promise.prototype.then = function (res, rej) {
const _this = this
if (_this.status == 'onFulfilled') {
res(_this.data)
return
}
if (_this.status == 'rejected') {
rej(_this.reason)
}
if (_this.status == "pending") {
_this.onFulFilledList.push(res)
_this.onRejectedList.push(rej)
}
}
Copy the code
The test code
function test() {
return new Promise((res, rej) = > {
setTimeout(function () {
console.time('promise')
console.log(123)
res('4')},2000)
})
}
test().then((
params
) => {
console.log(params)
console.timeEnd('a')})Copy the code
This implements the simplest asynchronous invocation of promises
The above content gives you a basic approach to ES6 Promise, hope to help you.