存在错误望指出
Promise
是什么?
Promise的用法:
new Promise((resolve, reject) => {
let 表达式 = true;
if (表达式) {
resolve();
} else {
reject();
}
}).then(() => {
// 当执行resolve时则会到这里
console.log("then");
}).catch(() => {
// 当执行reject时则会到这里
console.log("catch");
});
虽然执行了
resolve
或reject
之后程序并不会中断,但是两个如果先后执行,则只有先调用的有效。
例如这个代码:
// 控制台打印: ok
// catch
new Promise((resolve, reject) => {
reject();
resolve();
console.log("ok");
}).then(() => {
console.log("then");
}).catch(() => {
console.log("catch");
});
可以在调用方法时传入参数
// 输出:then 可以在这里传递数据
new Promise((resolve, reject) => {
resolve({
msg: "可以在这里传递数据",
});
}).then((res) => {
console.log("then", res.msg);
});
连续的
// 输出:
// 第一个then OK
// 第二个then 可以直接返回
// 第三个then 当然也可以返回Promise
// 结束
new Promise((resolve, reject) => {
resolve("OK");
}).then((res) => {
console.log("第一个then", res);
return "可以直接返回";
}).then((res) => {
console.log("第二个then", res);
return new Promise((resolve) => {
resolve("当然也可以返回Promise");
});
}).then((res) => {
console.log("第三个then", res);
console.log("结束");
});
为什么?
在以前如api请求、数据库操作、文件读写等涉及到异步处理的时候,通常都要求外部传入一个回调函数。
有时候需要连续做多个异步操作时,就会产生所谓的“回调地狱”
例如:
api请求((api请求返回) => {
文件读写(文件名, 内容, () => {
数据库操作(sql, () => {
// todo
});
});
});
在通过Promise改写后,就可以有效缓解或解决这个问题。
如:
new Promise((resolve, reject) => {
// todo
api请求((api请求返回) => {
// todo
resolve(api请求返回);
});
}).then((res) => {
文件读写(文件名, 内容, () => {});
// todo
return new Promise((resolve) => {
// todo
resolve();
});
}).then((res) => {
// todo
数据库操作(sql, () => {
// todo
});
});
从缩进就可以看出二者明显的差异
async/await
是什么?
先看一段代码:
// 输出:Promise { 1 }
async function func() {
// todo
return 1;
}
console.log(func());
从以上代码就可以明显看出来,被async修饰过的方法,其返回值是一个Promise对象。
以下是await使用方法:
// 输出:1
(async () => {
// await 必须运行在被async修饰的方法中
async function func() {
// todo
return 1;
}
console.log(await func()); // 直接输出了func的结果值
})();
而其中async部分等效于下面的代码
// 输出:1
(async () => {
function func() {
return new Promise((resolve) => {
resolve(1);
});
}
console.log(await func());
})();
async 可以将一个方法的返回值变成Promise对象
await 方法可以直接取到Promise中传入resolve的值
为什么?
借用前面描述”回调地狱“的例子,使用promise async/await的最佳实践。
// 对原来通过回调完成异步操作的方法使用Promise进行封装
function promise_api请求() {
return new Promise((resolve) => {
api请求((api请求返回) => {
resolve();
});
});
}
function promise_文件读写() {
return new Promise((resolve) => {
api请求(() => {
resolve();
});
});
}
function promise_数据库操作(sql) {
return new Promise((resolve) => {
数据库操作(sql, () => {
resolve();
});
});
}
// 封装完成后即可这样使用了
(async () => {
await promise_api请求();
await promise_文件读写();
await promise_数据库操作(sql);
})();
虽然这里代码量明显增加了不少,但是将这些常用方法进行统一封装,在开发使用时能更有效的降低复杂度,增加了可读性。
总之,用了都说好!
await时reject如何处理?
使用await后,resovle结果值可以直接获取,而reject则会抛出异常。使用try/catch即可
function promise_api请求() {
return new Promise((resolve, reject) => {
api请求((api请求返回) => {
reject();
});
});
}
(async () => {
try {
await promise_api请求();
} catch (e) {
// todo 将会执行这里的代码
}
})();