Promise
-
- 1. Meaning
- Second, the use of Promise
-
- 1. Promise constructor: Promise(executor) {}
- 2. Promise.prototype.then method: `(onResolved, onRejected) => {}`
- 3. Promise.resolve 方法: `Promise.resolve(value) => {}`
- 4. Promise.reject method: `Promise.resolve(reason) => {}`
- 5. Promise.all method: `Promise.all(iterable) => {}`
- 7. Promise.race method: Promise.race(iterable) => {}
- 3. Several key issues of promise
-
- 1. How to change the state of promise?
- 2. A promise specifies multiple success/failure callback functions, will they all be called?
- 3. Which one should change the promise state and specify the callback function first?
- 4. What determines the result state of the new promise returned by promise.then()?
- 5. How does promise chain multiple operation tasks?
- 6. Break promise chain?
1. Meaning
Promise isasynchronous programminga solution for
1. Concept
Simply put, it is a container that holds the results of events (usually an asynchronous operation) that will end in the future. Syntactically, Promise
an object from which messages for asynchronous operations can be obtained. Promise
Provide a unified API
, all kinds of asynchronous operations can be processed in the same way.
asynchronous programming: fs file operation, database operation, Ajax, timer;
2. Features
-
The state of the object is not affected by the outside world. The Promise object represents an asynchronous operation with three states
- pending: in progress
- fulfilled: has been successful
- rejected: failed
Only the result of an asynchronous operation can determine which state it is currently in, and no other operation can change this state.
-
Once the state changes, it will not change again, and this result can be obtained at any time. State changes have only two states from
pending
changing tofulfilled
and frompending
changing torejected
.
3. Basic usage
ES6 stipulates that Promise
an object is a constructor used to generate Promise
instances.
// Promise构造函数接受一个函数(执行器函数)作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
// 在异步操作成功时调用,并将异步操作的结果,作为参数value传递出去;
resolve(value);
} else {
// 在异步操作失败时调用,并将异步操作报出的错误,作为参数error/reason传递出去。
reject(error);
}
});
After the Promise instance is generated, you can use the then method to specify the callback functions of the resolved state and the rejected state respectively.
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
method can accept two callback functions as parameters.
- The first callback function is called when
Promise
the state of the object changesresolved
- The second callback function is called when
Promise
the state of the object changesrejected
.
Both functions are optional and do not have to be provided. They all accept Promise
the value passed from the object as a parameter.
// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => {
// 执行器函数
// 执行异步操作任务
setTimeout(() => {
const time = Date.now()
// 如果当前时间是偶数代表成功,否则失败
if (time % 2 == 0) {
// 如果成功,调用resolve(value)
resolve('成功的数据,time=' + time)
} else {
// 如果失败,调用reject(reason)
reject('失败的数据,time=' + time)
}
}, 1000);
})
p.then(
value => {
// 接收得到成功的value数据 onResolved
console.log('成功的回调', value) // 成功的回调 成功的数据,time=1615015043258
},
reason => {
// 接收得到失败的reason数据 onRejected
console.log('失败的回调', reason) // 失败的回调 失败的数据,time=1615014995315
}
)
4. Why use Promise
1. The way to specify the callback function is more flexible
Old: must be specified before starting the async task
// 1. 纯回调的形式
// 成功的回调函数
function successCallback(result) {
console.log("声音文件创建成功:" + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("声音文件创建失败:" + error);
}
// 必须先指定回调函数,再执行异步任务
createAudioFileAsync(audioSettings, successCallback, failureCallback) // 回调函数在执行异步任务(函数)前就要指定
Promise: start an asynchronous task => return a promise object => bind a callback function to the promise object (can even be specified after the asynchronous task ends)
// 2. 使用Promise
const promise = createAudioFileAsync(audioSettings); // 执行2秒
setTimeout(() => {
promise.then(successCallback, failureCallback) // 也可以获取
}, 3000);
2. Support chain calls, which can solve the problem of callback hell
Callback hell: Callback functions are nested, and the result of the asynchronous execution of the outer callback function is the condition for the execution of the inner nested callback function.
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result:' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
promise
Solving Callback Hell with Chained Calls
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log('Got the final result:' + finalResult)})
.catch(failureCallback)
Implementing Ajax with Promises
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
In the above code, getJSON is an encapsulation of the XMLHttpRequest object, which is used to issue an HTTP request for JSON data and return a Promise object. It should be noted that inside getJSON, both the resolve function and the reject function are called with parameters.
Second, the use of Promise
1. Promise constructor: Promise(executor) {}
- executor function:Synchronous execution (resolve, reject) => {}
- resolve function: the function resolve(value) called when the internal definition succeeds
- reject function: the function reject(reason) called when the internal definition fails
Description: The executor is the executor, which will immediately call back synchronously inside the Promise, and the asynchronous operation resolve/reject will be executed in the executor
2. Promise.prototype.then method:(onResolved, onRejected) => {}
指定两个回调(成功+失败)
(1) onResolved
Function: successful callback function(value) => {}
(2) onRejected
Function: callback function for failure(reason) => {}
Description: Specify value
the success callback for success and reason
the failure callback for failure, and return a new promise
object
2, Promise.prototype.catch method:p.(onRejected) => {}
Specify a callback for failure
(1) onRejected function: failed callback function (reason) => {}
Explanation: This is then()
syntactic sugar, equivalent to:then(undefined, onRejected)
new Promise((resolve, reject) => {
// excutor执行器函数
setTimeout(() => {
if(...) {
resolve('成功的数据') // resolve()函数
} else {
reject('失败的数据') //reject()函数
}
}, 1000)
}).then(
value => {
// onResolved()函数
console.log(value) // 成功的数据
}).catch(
reason => {
// onRejected()函数
console.log(reason) // 失败的数据
}
)
3. Promise.resolve method:Promise.resolve(value) => {}
Returns a success/failure promise
object
value
: success data or promise
object
1. If the incoming parameter is an object of non-Promise type, the returned result is a successful promise object
let p1 = Promise.resolve(521);
console.log(p1); // Promise {<fulfilled>: 521}
2. If the incoming parameter is Promise
an object, the result of the parameter determines resolve
the result of
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK'); // 成功的Promise
reject('Error');
}));
console.log(p2);
p2.catch(reason => {
console.log(reason);
})
4. Promise.reject method:Promise.resolve(reason) => {}
(1) reason
: Reason for failure
Description: Returns a failed promise
object
let p = Promise.reject(521);
let p2 = Promise.reject('iloveyou');
let p3 = Promise.reject(new Promise((resolve, reject) => {
resolve('OK');
}));
console.log(p);
console.log(p2);
console.log(p3);
Promise.resolve()
The / Promise.reject()
method is a syntactic sugar to quickly get the Promise object
5. Promise.all method:Promise.all(iterable) => {}
iterable
promise
: An iterable object containing n , such asArray
orString
- Returns a new one that succeeds
promise
only if all of them succeed, and fails directly if one fails.promise
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
let p1 = new Promise((resolve, reject) => {
resolve('OK');
})
let p2 = Promise.reject('Error');
let p3 = Promise.resolve('Oh Yeah');
const result = Promise.all([p1, p2, p3]);
console.log(result);
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
const pAll = Promise.all([p1, p2, p3])
const pAll2 = Promise.all([p1, p2])
//因为其中p3是失败所以pAll失败
pAll.then(
value => {
console.log('all onResolved()', value)
},
reason => {
console.log('all onRejected()', reason)
}
)
// all onRejected() 3
pAll2.then(
values => {
console.log('all onResolved()', values)
},
reason => {
console.log('all onRejected()', reason)
}
)
// all onResolved() [1, 2]
7. Promise.race method: Promise.race(iterable) => {}
iterable
promise
: An iterable object containing n , such asArray
orString
- Returns a new
promise
, first completedpromise
result state which is the final result state.
const pRace = Promise.race([p1, p2, p3])
// 谁先完成就输出谁(不管是成功还是失败)
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
pRace.then(
value => {
console.log('race onResolved()', value)
},
reason => {
console.log('race onRejected()', reason)
}
)
//race onResolved() 2
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.race([p1, p2, p3]);
console.log(result);
3. Several key issues of promise
1. How to change the state of promise?
(1) resolve(value)
: If the current is pending
will becomeresolved
(2) reject(reason)
: If it is currently, pending
it will become `rejected``
(3) Throwing an exception: If it is currently, pending
it will becomerejected
const p = new Promise((resolve, reject) => {
//resolve(1) // promise变为resolved成功状态
//reject(2) // promise变为rejected失败状态
throw new Error('出错了') // 抛出异常,promise变为rejected失败状态,reason为抛出的error
})
p.then(
value => {
},
reason => {
console.log('reason',reason)}
)
// reason Error:出错了
2. A promise specifies multiple success/failure callback functions, will they all be called?
Called when the promise changes to the corresponding state
const p = new Promise((resolve, reject) => {
//resolve(1)
reject(2)
})
p.then(
value => {
},
reason => {
console.log('reason',reason)}
)
p.then(
value => {
},
reason => {
console.log('reason2',reason)}
)
// reason 2
// reason2 2
3. Which one should change the promise state and specify the callback function first?
(1) Both are possible. Under normal circumstances, the callback is specified first and then the state is changed, but it is also possible to change the state first and then specify the callback
(2) How to change the state first and then specify the callback?
① Call resolve()/reject() directly in the executor
② Delay longer before calling then()
let p = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('OK');
// }, 1000); // 有异步就先指定回调,否则先改变状态
});
p.then(value => {
console.log(value);
},reason=>{
})
(3) When will the data be available?
① If the callback is specified first, then when the state changes, the callback function will be called to get the data
② If the state is changed first, then when the callback is specified, the callback function will be called to get the data
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1) // 改变状态
}, 1000)
}).then( // 指定回调函数 (先指定)
value => {
},
reason =>{
}
)
At this time, first specify the callback function, save the currently specified callback function; then change the state (at the same time specify the data), and then execute the previously saved callback function asynchronously.
new Promise((resolve, reject) => {
resolve(1) // 改变状态
}).then( // 指定回调函数
value => {
},
reason =>{
}
)
This way of writing, first change the state (at the same time specify the data), then specify the callback function (no need to save again), and directly execute the callback function asynchronously
4. What determines the result state of the new promise returned by promise.then()?
(1) Simple expression: determined by the execution result of the callback function specified by then()
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
});
console.log(result);
(2) Detailed expression:
① If an exception is thrown, the new promise becomes rejected, reason is the thrown exception
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//1. 抛出错误
throw '出了问题';
}, reason => {
console.warn(reason);
});
console.log(result);
② If any non-promise value is returned, the new promise becomes resolved, and value is the returned value
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//2. 返回结果是非 Promise 类型的对象
return 521;
}, reason => {
console.warn(reason);
});
console.log(result);
③ If another new promise is returned, the result of this promise will become the result of the new promise
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
//3. 返回结果是 Promise 对象
return new Promise((resolve, reject) => {
// resolve('success');
reject('error');
});
}, reason => {
console.warn(reason);
});
console.log(result);
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('onResolved1()', value)
},
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onResolved1() 1
// onResolved2() undefined
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('onResolved1()', value)
//return 2 // onResolved2() 2
//return Promise.resolve(3) // onResolved2() 3
//return Promise.reject(4) // onRejected2() 4
//throw 5 // onRejected2() 5
},
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onResolved1() 1
// onResolved2() undefined
// Promise {<fulfilled>: undefined}
// 对应输出如上所示
5. How does promise chain multiple operation tasks?
(1) promise
returns then()
a new chain call promise
that can be openedthen()
(2) then
Multiple synchronous/asynchronous tasks are connected in series through the chain call of
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value); // success
}).then(value => {
console.log(value); // undefined
})
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行任务1(异步)')
resolve(1)
}, 1000)
}).then(
value => {
console.log('任务1的结果', value)
console.log('执行任务2(同步)')
return 2 // 同步任务直接return返回结果
}
).then(
value => {
console.log('任务2的结果', value)
return new Promise((resolve, reject) => {
// 异步任务需要包裹在Promise对象中
setTimeout(() => {
console.log('执行任务3(异步)')
resolve(3)
}, 1000)
})
}
).then(
value => {
console.log('任务3的结果', value)
}
)
// 执行任务1(异步)
// 任务1的结果 1
// 执行任务2(同步)
// 任务2的结果 2
// 执行任务3(异步)
// 任务3的结果 3
6. Break promise chain?
(1) When using promise
the then
chain call of , it will be interrupted in the middle, and the subsequent callback function will not be called
(2) Methods:pendding
Return a state promise
object in the callback function
new Promise((resolve, reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolved1()', value)
return 2
}
).then(
value => {
console.log('onResolved2()', value)
return 3
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(
reason => {
console.log('onRejected1()', reason)
}
).then(
value => {
console.log('onResolved4()', value)
},
reason => {
console.log('onRejected2()', reason)
}
)
// onRejected1() 1
// onResolved4() undefined