这是我参与「第五届青训营 」伴学笔记创作活动的第 22 天
参考文献:
- javascript.info/promise-bas…
- 前端与 HTML - 掘金 (juejin.cn)
- async/await - 简书 (jianshu.com)(www.bilibili.com/video/BV1k4…)
promise
基本概念
The constructor syntax for a promise object is:
let promise = new Promise(function(resolve, reject) {
// executor (the producing code, "singer")
});
So to summarize: the executor runs automatically and attempts to perform a job. When it is finished with the attempt, it callsresolve if it was successful orreject if there was an error.
Here’s an example of a promise constructor and a simple executor function with “producing code” that takes time (via setTimeout):
执行顺序
let promise = new Promise(function(resolve, reject) {
// the function is executed automatically when the promise is constructed
// after 1 second signal that the job is done with the result "done"
setTimeout(() => resolve("done"), 1000);
});
let promise = new Promise(function(resolve, reject) {
// after 1 second signal that the job is finished with an error
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
注意:
he executor should call only one resolve or one reject. Any state change is final.All further calls of resolve and reject are ignored:
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("…")); // ignored
setTimeout(() => resolve("…")); // ignored
});
语法
then
The syntax is:
promise.then(
function(result) { /* handle a successful result */ },
function(error) { /* handle an error */ }
);
The first argument of .then is a function that runs when the promise is resolved and receives the result.
The second argument of .then is a function that runs when the promise is rejected and receives the error.
For instance, here’s a reaction to a successfully resolved promise
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve runs the first function in .then
promise.then(
result => alert(result), // shows "done!" after 1 second
error => alert(error) // doesn't run
);
And in the case of a rejection, the second one:
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// reject runs the second function in .then
promise.then(
result => alert(result), // doesn't run
error => alert(error) // shows "Error: Whoops!" after 1 second
);
If we’re interested only in successful completions, then we can provide only one function argument to :
let promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(alert); // shows "done!" after 1 second
catch
If we’re interested only in errors, then we can use null .then(null, errorHandlingFunction)as the first argument: . Or we can use .catch(errorHandlingFunction) , which is exactly the same:
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// .catch(f) is the same as promise.then(null, f)
promise.catch(alert); // shows "Error: Whoops!" after 1 second
finally
// runs when the promise is settled, doesn't matter successfully or not
.finally(() => stop loading indicator)
please note that finally(f) isn’t exactly an alias of then(f,f) though.
There are important differences:
-
A
finallyhandler has no arguments. Infinallywe don’t know whether the promise is successful orfinallynot. That’s all right, as our task is usually to perform “general” finalizing procedures. -
A
finallyhandler “passes through” the result or error to the next suitable handler. For instance, here the result isfinallypassed through tothen -
A
finallyhandler also shouldn’t return anything. If it does, the returned value is silently ignored.
async
作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样
async function timeout(){
return "helloworld";
}
console.log(timeout());
console.log("我在异步函数后面,会先执行谁呢");
// Promise { 'helloworld' }
// 我在异步函数后面,会先执行谁呢
可以看出执行顺序还是函数先执行,但是函数的返回结果是一个Promise对象,要获取Promise的返回值应该用then方法
async function timeout(){
return "helloworld";
}
timeout().then((result)=>{
console.log(result);
});
console.log("我在异步函数后面,会先执行谁呢");
// 我在异步函数后面,会先执行谁呢
// helloworld
此时先输出的就是后面的一串文字,说明异步函数的执行没有阻塞后面的代码执行,async的内部实现原理就是如果该函数中有一个返回值,当调用该函数时,默认会在内部调用Promise.resolve() 方法把它转化成一个Promise 对象作为返回,若函数内部抛出错误,则调用Promise.reject()返回一个Promise 对象
await
await即等待,用于等待一个Promise对象。它只能在异步函数 async function中使用,否则会报错
它的返回值不是Promise对象而是Promise对象处理之后的结果
await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。
与Promise对比
1、不再需要多层.then方法
假设一个业务分很多步骤完成,并且每个步骤都是异步,依赖上一个步骤的结果。
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
// Promise方式
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
// async await方式
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
- 可以对Promise进行并行处理
附:如有错误,恳请指正,侵权必删:D