Part1.2 异步编程
文章内容输出来源:拉勾教育大前端训练营
异步编程
- Javascript语言的执行环境是单线程,一次只能完成一件任务,必须排队.js同步执行加载大数据及运行复杂算法导致页面的白屏时间过长,浏览器假死现象.会带来不好的用户体验.而异步编程解决了这一个问题,不在等待返回.而是等到有返回值有的时候或者该执行的时候进入消息队列中等待被调用.
- 异步编程的基础方法就是回调函数,其他方法还有事件监听,信息发布/订阅,Promise,Generator,async/awit,setTimeOut/setInterval
- 异步编程最好的例子就是AJAX
同步模式
- 概述:排队执行,只有上一个任务结束才会执行下一个任务,单线程模式下都是同步执行代码的.
- 问题:排队执行,会阻塞执行队列.
异步模式
- 概述: 异步执行不会等待任务结束,开启过后立即开启下一个任务,通过回调函数执行后续逻辑业务.同时处理大量的耗时任务.
- 问题: 代码的执行顺序混乱,不利于阅读
回调函数
- 概述:异步编程的基本用法
Promise 承诺
- 概述:一个对象,表述一个任务成功(fulfilled)或者失败(rejected).状态不可更改.解决回调地狱问题
- 问题:嵌套调用,使用.then 来避免 传统的回调地狱问题.实现代码的扁平化
code
const promise = new Promise(function (resolve, reject) {
resolve(100);
// reject(new Error("promise rejected"));
});
promise.then(
function (value) {
console.log("resolved", value);
},
function (error) {
console.log("rejected", error);
}
);
promise 异常捕获
- 链式调用.catch()捕获异常,可以传递错误信息
- 在.then内部注册onrejected事件只能捕获当前promise的异常
- 全局注册 unhandledrejection 处理没有被捕获的错误信息(不推荐使用)
code
function ajax(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("get", url);
xhr.responseType = "jsonp";
xhr.onload = function () {
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
xhr.send();
});
}
// ajax("./code/mock.json").then(
// function (res) {
// console.log(res);
// },
// function (err) {
// console.log(err);
// }
// );
ajax("./code/mock.json")
.then(function (res) {
console.log(res);
})
.catch(function (err) {
console.log(err);
});
promise 静态方法
- resolve 快速创建成功状态的promise对象
- reject 快速创建失败状态的promise对象
promise 并行请求
- all 同步并行执行 等待所有组合的任务成功结束
- race 并行执行 只会等待第一个执行任务完成
promise 执行顺序
- 宏任务 任务完成后 其他业务逻辑重新排队执行
- 微任务 任务完成 其他业务逻辑立即执行
Generator 生成器 扁平化异步调用
- 概述:
- '*'代表 Generator函数;
- next()执行函数体;
- yield关键词,暂停生成器执行,直到外部.next()再执行后面的语句.yield后面的值作为返回对象的value值返回
- throw() 抛出异常
code
// function* main() {
// try {
// console.log('start');
// const msg = yield "log1";
// console.log(msg);
// const msg1 = yield "log2";
// console.log(msg1);
// const msg2 = yield "log3";
// console.log(msg2);
// } catch (error) {
// console.log("main:" + error);
// }
// }
// const g = main()
// const g1=g.next("233")
// console.log(g1)
// g.next("234")
// g.throw("error")
//genterator 配合promise 异步执行
function* main() {
try {
console.log("start");
const ajax1 = yield Promise.resolve("msg1");
console.log(ajax1);
const ajax2 = yield Promise.resolve("msg2");
console.log(ajax2);
} catch (error) {
console.log("main:" + error);
}
}
// const g = main();
// const result = g.next();
// result.value.then((data) => {
// const result1 = g.next(data);
// if (result1.done) return;
// result1.value.then((data) => {
// const result2 = g.next(data);
// if (result2.done) return;
// result2.value.then((data) => {
// const result3 = g.next(data);
// if (result3.done) return;
// });
// });
// });
//封装 生成器函数调用
function co(generator) {
const g = generator();
function handleResult(result) {
console.log(result);
if (result.done) return;
// console.log(result.value);
result.value
.then((data) => {
handleResult(g.next(data));
})
.catch((err) => console.log(err));
}
handleResult(g.next());
}
co(main);