1.什么是异步:任务与任务之间是不存在等待的关系 前一个任务完成之后等待回调 中间并不影响后面队列中任务的执行
1.首先记住一句话 —— JS 是单线程的语言,所谓“单线程”就是一根筋,对于拿到的程序,一行一行的执行,上面的执行为完成,就傻傻的等着。
var i, t = Date.now()
for (i = 0; i < 100000000; i++) {
}//等待循环遍历结束 才会进行下面的
console.log(Date.now() - t) // 250 (chrome浏览器)
通过上面的程序我们可以了解到 如果是单纯的之sing程序 我们可以等 但是对于再浏览区里面运行的 代码 我们不可能因为某一段代码的执行占用大量的时间而傻傻的等着 这时异步的理念就显得尤为关键了。
2.引出异步概念的原因-- 避免 DOM 渲染冲突
// 避免 DOM 渲染冲突
// 1.浏览器需要渲染DOM
// 2.JS可以修改DOM结构
// 3,JS执行的时候,浏览器DOM渲染会暂停
// 4.两端JS也不能同时修改(同时修改避免DOM冲突)
// 5,webeorker支持多线程但是不能操作DOM
1.说到异步 我们就要引出单线程的概念
2 浏览器内核的多线程
浏览器的内核是多线程的,他们在内核的控制下互相配合以保持同步,一个浏览器至少实现三个常驻的线程:
1.javascript引擎线程,(用于事件处理的机制)
2.GUI渲染线程,
3.浏览器事件触发线程。
1)js引擎,基于事件驱动单线程执行的,js引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
2)GUI线程,当界面需要重绘或由于某种操作引发回流时,该线程就会执行。它和JS引擎是互斥的。
3)浏览器事件触发线程,当一个事件被触发时,该线程会把事件添加到待处理队列的队尾,等待js引擎的处理,这些事件可来自JavaScript引擎当前执行的代码块如,setTimeOut, 也可以来自浏览器内核的其他线程如鼠标点击,AJAX异步请求等,但由于JS的单线程关系,所有这些事件都得排队等待JS引擎处理。
3 事件循环机制
3.异步的解决方案-异步编程实现
1 回调函数
// 一个简单的封装
function want() {
console.log('这是你想要执行的代码');
}
function fn(want) {
console.log('这里表示执行了一大堆各种代码');
// 其他代码执行完毕,最后执行回调函数
want && want();
}
fn(want);
doSomethingAsync1(function(){
doSomethingAsync2(function(){
doSomethingAsync3(function(){
doSomethingAsync4(function(){
doSomethingAsync5(function(){
// code...
});
});
});
});
});
总结:上面代码我们可以看到在代码层面嵌套不太深的情况下我们还好维护,而一旦嵌套层次过多就会形成 回调金字塔 很难维护--回调地狱
2 事件监听(事件发布/订阅)
》》》事件监听是一种非常常见的异步编程模式,它是一种典型的逻辑分离方式,对代码解耦很有用处。通常情况下,我们需要考虑哪些部分是不变的,哪些是容易变化的,把不变的部分封装在组件内部,供外部调用,需要自定义的部分暴露在外部处理。从某种意义上说,事件的设计就是组件的接口设计。
1)jQuery事件监听
$('#btn').on('myEvent', function(e) {
console.log('There is my Event');
});
$('#btn').trigger('myEvent');
2)发布/订阅模式
var PubSub = function(){
this.handlers = {};
};
PubSub.prototype.subscribe = function(eventType, handler) {
if (!(eventType in this.handlers)) {
this.handlers[eventType] = [];
}
this.handlers[eventType].push(handler); //添加事件监听器
return this;//返回上下文环境以实现链式调用
};
PubSub.prototype.publish = function(eventType) {
var _args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, _handlers = this.handlers[eventType]; i < _handlers.length; i++) {
_handlers[i].apply(this, _args);//遍历事件监听器
}
return this;
};
var event = new PubSub;//构造PubSub实例
event.subscribe('list', function(msg) {
console.log(msg);
});
event.publish('list', {data: ['one,', 'two']});
//Object {data: Array[2]}
3.3 Promise对象
import axios from 'axios';
import iView from "iview";
let qs = require("qs");
axios.defaults.timeout = 50000;
axios.defaults.baseURL = '';
function http(config) {
return new Promise((resolve, reject) => {
axios(config).then(response => {
let reqUrl = response.request.responseURL;
try {
if (!reqUrl.endsWith("callNum.action") && !reqUrl.endsWith("getMicroDeviceStatus.action")) {
if (response.data.code === 401) {
top.window.location.href = "/login.html";
} else if (response.data.code === 403) {
iView.Message.error('权限不足,禁止访问!');
} else if (response.data.code === 500) {
if (response.data.msg) {
iView.Message.error(response.data.msg);
} else {
iView.Message.error('网络访问失败,请稍后再试!');
}
} else if (response.data.code !== 200) {
iView.Message.error(response.data.msg);
}
}
} catch (e) {}
resolve(response.data);
}).catch(err => {
if (!reqUrl.endsWith("getMicroDeviceStatus.action")) {
iView.Message.error('网络请求发生错误!');
}
reject(err);
});
});
}
/**
* 封装get方法
* @param url 要请求的url地址
* @param params 请求的参数
* @returns {Promise}
*/
export function fetch(url, params = {}) {
return http({
method: 'GET',
url: url,
params: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'platform': 'PC'
}
});
}
/**
* 封装post请求
* @param url 要请求的url地址
* @param data 请求的参数
* @returns {Promise}
*/
export function post(url, data = {}) {
return http({
method: 'POST',
url: url,
data: qs.stringify(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'platform': 'PC'
}
});
}
/**
* 封装patch请求
* @param url 要请求的url地址
* @param data 请求的参数
* @returns {Promise}
*/
export function patch(url, data = {}) {
return http({
method: 'PATCH',
url: url,
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'platform': 'PC'
}
});
}
/**
* 封装put请求
* @param url 要请求的url地址
* @param data 请求的参数
* @returns {Promise}
*/
export function put(url, data = {}) {
return http({
method: 'PUT',
url: url,
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'platform': 'PC'
}
});
}
//get请求
async handleGetRulesData(){
let reqUrl = this.global.baseUrl + "/pc/robotAnalyzer/rule";
let params = {};
let data = await this.$fetch(reqUrl,params);
if(data.code==200){
}
},
、、post请求
async handleRobotAnalySort(){
let reqUrl = this.global.baseUrl + "/pc/robotAnalyzer/sort/"+this.robotId;
let params = {};
let data = await this.$post(reqUrl,params);
if(data.code==200){
}
},