"Code tailor" provides technical-related information and a series of basic articles for front-end developers. Follow the "Novices of Xiaoheshan" public account on WeChat to get the latest articles in time.
Preface
Before starting to learn, what we want to tell you is that this article is a summary of chapter 16084fe5d9f153 "Promise" "Introduction to ECMAScript6". If you have mastered the following knowledge items, you can skip this link directly Go to exercise
- What is Promise?
- How to create and use Promise
- Reasons and advantages and disadvantages
If you have forgotten some parts, 👇🏻 is ready for you!
Learning link
Summary
concept
APromise
object represents a value that is not necessarily known whenPromise
It allows you to associate the final success return value or failure reason of an asynchronous operation with the corresponding handler. This allows asynchronous methods to return values like synchronous methods: asynchronous methods do not return the final value immediately, but return aPromise
so that the value can be given to the user at some point in the future.
Three states:
- Pending: The initial state, neither being honored nor rejected.
- Fulfilled: means the operation completed successfully.
- Rejected (rejected): Means the operation failed.
Create and use
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo')
}, 300)
})
promise1
.then((value) => {
console.log(value) // expected output: "foo"
})
.catch((error) => {
//发生错误时调用
console.log(error)
})
.finally(() => {
//无论正确或错误,都会执行
console.log('执行完毕')
})
console.log(promise1)
// expected output: [object Promise]
- new Promise (executor)
Create a newPromise
object. This constructor is mainly used to wrap functions that have not yet added promise support. The parameters (executor
) are two:resolve
function, called when the operation is successfully completed;reject
function, called when an error occurs
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo')
}, 300)
})
promise1.then((value) => {
console.log(value)
// expected output: "foo"
})
console.log(promise1)
// expected output: [object Promise]
Common method
- Promise.all(iterable)
Promise.all()
method of receiving a Promiseiterable
Type (Note:Array
,Map
,Set
belongES6
theiterable
type) input, and only returns aPromise
instance.resolve
callback is executed on all inputsPromise
ofresolve
pullback is over, or enter theiterable
not inPromise
the time. Reject callback execution means that as long as any inputPromise
orreject
callback is executed or input illegalPromise
an error will be thrown immediately, andreject
is the first error message thrown.
const promise1 = Promise.resolve(3)
const promise2 = 42
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo')
})
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values)
})
// expected output: Array [3, 42, "foo"]
- Promise.allSettled(iterable)
ThePromise.allSettled()
method returns all in a givenPromise
havefulfilled
orrejected
afterPromise
, and having an array of objects, each object represents a correspondingPromise
results. It is usually used when you have multiple asynchronous tasks that do not depend on each other to complete successfully, or when you always want to knowPromise
const promise1 = Promise.resolve(3)
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'))
const promises = [promise1, promise2]
Promise.allSettled(promises).then((results) =>
results.forEach((result) => console.log(result.status)),
)
// expected output:
// "fulfilled"
// "rejected"
- Promise.race(iterable)
Promise.race(iterable)
method returns aPromise
, once a certainPromise
in the iterator is resolved or rejected, the returnedPromise
will be resolved or rejected.
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one')
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two')
})
Promise.race([promise1, promise2]).then((value) => {
console.log(value)
// Both resolve, but promise2 is faster
})
// expected output: "two"
Reasons and advantages and disadvantages
advantages:
- After the status is changed, it will not change again, and this result can be obtained at any time
- Asynchronous operations can be expressed in a synchronous operation process, avoiding nested callback functions
- To a certain extent solves the readability problem of callback hell
Disadvantages:
- Unable to cancel promise
- When in the pending state, it is impossible to know which stage it is currently progressing to
- The code is redundant, and the semantics will be unclear when there are a bunch of tasks
The "callback hell" brought by asynchronous callback
, logical confusion, high coupling, and poor readability gave birth to Promise
. For more knowledge, please click here Asynchronous development history of JavaScript
Self-test
One: What is the final output of the following code?
const first = () =>
new Promise((resolve, reject) => {
console.log(3)
let p = new Promise((resolve, reject) => {
console.log(7)
setTimeout(() => {
console.log(5)
resolve(6)
}, 0)
resolve(1)
})
resolve(2)
p.then((arg) => {
console.log(arg)
})
})
first().then((arg) => {
console.log(arg)
})
console.log(4)
2: The red light turns on once every three seconds, the green light turns on once every second, and the yellow light turns on once every 2 seconds; how to make the three lights alternately and repeatedly turn on? (Implemented with Promise) Three lighting functions already exist:
function red() {
console.log('red')
}
function green() {
console.log('green')
}
function yellow() {
console.log('yellow')
}
3: Implement the mergePromise function, execute the passed array in order, and put the returned data in the array data.
const timeout = (ms) =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ms)
})
const ajax1 = () =>
timeout(2000).then(() => {
console.log('1')
return 1
})
const ajax2 = () =>
timeout(1000).then(() => {
console.log('2')
return 2
})
const ajax3 = () =>
timeout(2000).then(() => {
console.log('3')
return 3
})
const mergePromise = (ajaxArray) => {
// 在这里实现你的代码
}
mergePromise([ajax1, ajax2, ajax3]).then((data) => {
console.log('done')
console.log(data) // data 为 [1, 2, 3]
})
// 要求分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]
Problem analysis
One,
Answer:
// 运行结果:
// => 3
// => 7
// => 4
// => 1
// => 2
// => 5
This question mainly understands the js execution mechanism.
In the first round of event loop, execute the macro task first, the main script,new Promise
immediately, output 3, execute the p new Promise
operation, output 7, find setTimeout
, put the callback function into the next round of task queue ( Event Quene
), p of then
, for now Named then1
, put it into the micro task queue, and first
also has then
, named then2
, put it into the micro task queue. Execute console.log(4)
, output 4, and the macro task execution ends.
Then execute the micro task, execute then1
, output 1, execute then2
, output 3.
The first round of event loop ends and the second round begins. The second round of the event loop inside the first execution of the macro task, which is setTimeout
callback, output 5.resolve(6)
will not take effect because of p Promise
state once the change will not change.
two,
Answer:
var light = function (timmer, cb) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
cb()
resolve()
}, timmer)
})
}
var step = function () {
Promise.resolve()
.then(function () {
return light(3000, red)
})
.then(function () {
return light(2000, green)
})
.then(function () {
return light(1000, yellow)
})
.then(function () {
step()
})
}
step()
Three seconds once the red light, a green light one second, a bright yellow 2 seconds, 3 seconds means that, once executed red
function, two seconds to perform a green
functions, one second to perform a yellow
function alternately repeated continuously lit, It means that these 3 functions are always executed in this order, and this step can be realized by using recursion.
Of course, other methods can be used to achieve the effect shown. There are many methods, and only one method is provided here.
three,
Answer:
// 保存数组中的函数执行后的结果
var data = []
// Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象。
var sequence = Promise.resolve()
ajaxArray.forEach(function (item) {
// 第一次的 then 方法用来执行数组中的每个函数,
// 第二次的 then 方法接受数组中的函数执行后返回的结果,
// 并把结果添加到 data 中,然后把 data 返回。
// 这里对 sequence 的重新赋值,其实是相当于延长了 Promise 链
sequence = sequence.then(item).then(function (res) {
data.push(res)
return data
})
})
// 遍历结束后,返回一个 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data,
// 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。
return sequence
First of all ajax1
, ajax2
, ajax3
are functions, but these functions will return a Promise
after execution. According to the requirements of the topic, we only need to execute these three functions in order, and then put the results in data
, but these functions are all Asynchronous operation, want to execute in order, and then output 1, 2, 3 is not so simple, look at an example.
function A() {
setTimeout(function () {
console.log('a')
}, 3000)
}
function B() {
setTimeout(function () {
console.log('b')
}, 1000)
}
A()
B()
// b
// a
In the example, we execute A in order, but the output result of B is b. For these asynchronous functions, a is not executed in order, and then the latter is executed. This question is to use Promise
control the asynchronous process. We have to find a way to make these functions execute after one is executed, and then execute the next.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。