目录
异步
回调
异步与回调的关系
如何判断异步
Promise
一、异步
不能直接拿到结果,如
setTimeout
,要等到定好的事件之后才能拿到结果。
二、回调
写好一个函数却不立即使用,而是给别人调用的函数。
回调举例
在以下的例子中,
f1就是回调
function f1(value) {
console.log("我是f1:" + value);
}
function f2(fn) {
fn("我是f2,调用了f1");
}
f2(f1);
三、异步与回调的关系
关联
异步任务需要在得到结果时通知 js 来拿结果。但是怎么通知呢?
写一个函数给浏览器,异步任务完成时浏览器调用该函数即可。同时将结果作为参数传给该函数。这个函数也就是
回调函数
。
区别
异步任务需要用到回调函数来拿取通知结果
但是回调函数不一定只用在异步任务里,回调还能用在同步任务中。如
array.forEach(n=>console.log(n))
就是一个同步回调。
四、如何判断异步
异步
setTimeout
AJAX(即 XMLHttpRequest)
addEventListener
- 更多异步后续更新
五、Promise
为什么要有Promise?
- 异步编程的统一解决方案
- 异步任务有两个结果时(成功或者失败)使用
- 规范回调的名字和顺序
- 方便捕获错误
- 避免出现
回调地狱
Promise的状态
待定(pending)
:初始状态,即没有兑现,也没有拒绝已兑现(fulfilled)
:意味着操作已完成已拒绝(rejected)
:意味着失败
待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个原因(错误)被拒绝(rejected)。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。
Promise使用的姿势
// 在封装时使用
const fn = function f1() {
return new Promise((resolve, reject) => {
// 做一些异步操作
if (成功) {
resolve(someValue);
}
else if (失败) {
reject(elseValue);
}
});
};
// 创建Promise实例对象时使用
const xxx = new Promise((resolve, reject) => {});
// 使用.then(success,fail)传入调用成功和失败函数
xxx.then(success_fn, fail_fn);
// 使用catch捕获错误
xxx.catch((err) => {
console.log("错误原因:" + err);
});
使用Promise简单封装ajax
const ajax = (method, url, options) => {
return new Promise((resolve, reject) => {
const { success, fail } = options;
const request = new XMLHttpRequest();
request.open(method, url);
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status < 400) {
resolve(request.response);
} else if (request.status > 400) {
reject(request);
}
}
};
request.send();
});
};
// 使用封装的ajax
ajax("GET", "/xxx").then(
(response) => {},
(request) => {}
);
小结
- return new Promise((resolve,reject)=>{})
- 任务成功调用:resolve(result),任务失败调用:reject(error)
- resolve 和 reject 会再去调用成功和失败函数
- 使用.then(success,fail)传入成功和失败函数
- 使用.catch((err)=>{})捕获错误