What Promise
An asynchronous solution
For example, multiple setTimeout() nested causes callback hell
setTimeout(function() {
// do something..
setTimeout(function() {
// dosomething.. }}, 1000), 1000)Copy the code
You can solve it with Promise
new Promise(function(resolve, reject){
setTimeout(function() {
// do something..
resolve(res)
}, 1000)
}).then(res => {
setTimeout(function() {
// do something..
return res
}, 1000)
}).then(res => {
setTimeout(function() {
// do something..
return res
}, 1000)
}).catch(err => {
console.log(err)
})
Copy the code
How do you use Promise?
new Promise(function(resolve, Reject){resolve(res) // enter. Then () reject(res) // enter. Catch ()}). Then (res => {console.log(res)}). console.log(err) })Copy the code
Characteristics of Promise
- Once a Promise state changes, it is irreversible and cannot be changed
new Promise(function(resolve, Reject){resolve(res) {reject(res) {error => {console.log(res)}). Catch (err => {error => {console.log(res)}). console.log(err) })Copy the code
- Promise’s then method parameter expects to receive a function, and if non-functions are passed in, value penetration occurs
new Promise(function(resolve, reject){
resolve('123')
}).then('res').then(res => {console.log(res) // prints out the '123' value through to the next onethenThe inside})Copy the code
new Promise(function(resolve, reject){
resolve('123')
}).then('res').catch(res => {console.log(res) // values do not penetrate into catch})Copy the code
- The Promise callback is synchronous, and the THEN callback is asynchronous
new Promise(function(resolve, reject){
console.log(1)
resolve('123')
}).then(res => {
console.log(2)
console.log(res)
return(`${res}4`)
}).then(res => {
console.log(3)
console.log(res)
})
console.log(4)
Copy the code
= = = = results
1, 4, 2, 123, 3, 1234Copy the code
- Then () returns a Promise object if there is a return. If == throws an exception ==, a Reject Promise is returned and a catch is entered. The return value of the previous THEN is the argument received by the next THEN.
new Promise(function(resolve, reject){
resolve('123')
}).then(res => {
console.log(res)
throw new Error('this is an error')}).then(res => {console.log(res)}).catch(err => {console.log(err))Copy the code
== must throw error, if return then ==
new Promise(function(resolve, reject){
resolve('123')
}).then(res => {
console.log(res)
return new Error('this is an error'}).then(res => {console.log(res) // enterthenThis is an error}). Catch (err => {console.log(err)})Copy the code
- A return Promise in a callback to then goes into wait state until the return Promise changes
new Promise(function(resolve, reject){
resolve('123')
}).then(res => {
return new Promise(function(resolve, reject) {
setTimeout(function(){
resolve('456') // Print 456 after 3 seconds // reject('789') // 3秒后打印789
}, 3000)
}) // returnThen (res => {console.log(res) // prints 456 after 3 seconds}). Catch (err => {console.log(err) // prints 789 after 3 seconds}).Copy the code
== The return is executed only after the promise state changes
The return must return a Promise, but any other value returned is a successful callback, and only the new Promise will wait
new Promise(function(resolve, reject){
resolve('123')
}).then(res => {
return setTimeout(function(){console.log(888) // prints 888 after 3 seconds}, 3000)}). Then (res => {console.log(res) // prints a string of numbers without waiting, }). Catch (err => {console.log // will not enter here})Copy the code
Javascript asynchrony
Javascript execution order
- JavaScript scans the code first
- Main thread, macro task queue, micro task queue
- After the main thread is executed, query the microtask queue first. If any task exists, the execution is complete
- Then query the macro task queue, if there are tasks in the macro task queue, take a task in the macro task to the main thread, execute it, and then ask the micro task after execution… And so on
For example, Promise belongs to a microtask and setTimeout belongs to a macro task
setTimeout(() => {
console.log('set1')});let p1 = new Promise((resolve, reject) => {
console.log('promise1')})setTimeout(() => {
console.log('set2')
})
p1.then(() => {
console.log('then1')
})
console.log(2)
Copy the code
The execution result
promise1
2
then1
set1
set2
Copy the code
- Set1 enters the macro task queue
- P1 (new Promise) synchronization, directly execute // promise1
- Set2 enters the macro task queue
- P1. Then asynchronous entry to micro task queue
- Console 2 directly execute // 2
- Execute the microtask queue p1.then // then1
- Macro task set1 to the main thread to execute // set1
- Void microtask, macro task set2 to the main thread execution // set2
- The end of the
setTimeout(() => {
console.log('set1')
new Promise((resolve, reject) => {
console.log('promise2')
resolve(2)
}).then(res => {
console.log('then2')})});let p1 = new Promise((resolve, reject) => {
console.log('promise1')
resolve(2)
})
setTimeout(() => {
console.log('set2')
})
p1.then((res) => {
console.log('then1')
})
console.log(2)
Copy the code
The execution result
promise1
2
then1
set1
promimse2
then2
set2
Copy the code
- scanning
- Set1 enters the macro task queue
- P1 Perform // promise1 for synchronization
- Set2 enters the macro task queue
- P1. Then asynchronous entry to micro task queue
- Console 2 directly execute // 2
- The microtask queue p1.then executes // then1
- Macro task set1 is transferred to the main thread for execution, and the macro task set1 is transferred to the main thread for execution, and the macro task set1 is transferred to the main thread for execution, and the macro task set1 is transferred to the main thread for execution
- When the main thread completes, look for the microtask and execute promise2. Then // then2
- Macro task set2 is removed to the main thread to execute // set2
Fulfill a promise yourself
// Call resolve -thenThe resolveArr () method adds the callback to the resolveArr- executes the entire resolveArr and changes the state to return the new promise var isFunction =function(fn) {
if (typeof fn === 'function') {
return true
} else {
return false
}
}
Function.prototype.bind = function(context) {
var self = this
return functionCall () {self.apply(context, arguments)}thenRegister a task callback, resolve triggers, to execute thisthenRegister function offunction mypromise(handle) {
this.status = 'PENDING'This. ResolveArr = []thenThis. RejectArr = [] // reject callback queue this. Resolve =function(val) {// Execute resolveArr to change myPromise stateif(this.status ! = ='PENDING') return// State is irreversible from this control this.status ='RESOLVE'
this.val = val
let cb;
setTimeout(() => {// resolveArr all executethenThis becomes asynchronous (important)while(cb = this.resolar.shift ()) {// set resolveArr to trueif (isFunction(cb)) {
cb(val)
}
}
})
}
this.reject = function(err) {
if(this.status ! = ='PENDING') return// State is irreversible from this control this.status ='REJECT'
this.val = err
}
// thenResolve () {// this. Resolve (); // This. Resolve ()bind this
handle(this.resolve.bind(this), this.reject)
} catch(err) {
throw err
}
}
// thenThe method is called by a Promise object, so put it in prototype myPromise.prototype. Then =function(suc, err) {
const val = this.val
const status = this.status
returnNew myPromise ((sucnext, errnext) => {// MyPromise ((sucnext, errnext) =>let _fn = undefined
let _handle = undefined
let run = function() {
try{
console.log(123)
if(! isFunction(_handle)) { //thenIt's not coming infunction_fn(val)}else {
let res = _handle(val)
console.log(sucnext)
sucnext(res)
}
} catch(err) {
errnext(err) // thenThrow an error catch to reject}} //let success = function() {
// try{
// if(! isFunction(suc)) { // resolve(suc) // }else {
// let res = suc(val)
// resolve(res)
// }
// } catch(err) {
// reject(err) // thenThrow an error catch, reject //} //} //let fail = function() {
// try{
// if(! isFunction(suc)) { // reject(suc) // }else {
// let res = err(val)
// resolve(res)
// }
// } catch(err) {
// reject(err) // thenReject //} //} switch (status) {case 'PENDING':
this.resolveArr.push(suc)
this.rejectArr.push(suc)
break
case 'RESOLVE':
_fn = resolve
_handle = suc
run()
// success()
break
case 'REJECT':
_fn = reject
_handle = err
run()
// fail()
break
}
})
}
new mypromise(function(resolve, reject) {
setTimeout(function() {
resolve(4)
}, 3000)
console.log(33)
}).then(res => {
console.log(res)
})
Copy the code