异步编程之promise,任务队列,事件循环

异步编程

我们先来看一看同步编程思想是怎样的,就是一行一行的按顺序执行代码

function createData(){
	return parseInt(Math.random()*(90-50)+50);
}

var obj = {
	data:100,
	tool:function(){
		// 同步的设计思想
		var data = createData();
		this.data = data;	
	}
}
obj.tool();
console.log(obj.data);

再来看看异步编程思想,就是可以重新在开一个线程来执行代码

// 异步的设计思想,回调函数
function createData(callback){
	callback(parseInt(Math.random()*(90-50)+50));
}

var obj = {
	data:100,
	tool:function(){
		createData((n) => {  // n表示createData产生的数据
			this.data = n;
		} );
	}
}
obj.tool();
console.log(obj.data);

异步函数

console.log(1);
// fn函数不可能是异步函数,但是js的底层 c/c++是有不阻塞代码的异步函数的
fn(function(){
	console.log(3)
},1000); // 异步阻塞函数
console.log(5);
// 例如,计时器,数据库操作,读取文件,promise等等耗时的一般都会设计成不阻塞的线程
setTimeout(function(){
	console.log(4)
},1000);
console.log(2);
// 打印结果 因为fn是异步阻塞函数,执行到这里就被阻塞了,就报错了

当我们写了两个setTimeout函数时,如果睡眠时间一样那么谁先写谁先执行,如果睡眠时间不一样,就是谁先醒谁就先执行

setTimeout(() => {console.log(11)},2000 );
setTimeout(() => {console.log(22)},1000 );
// 打印结果 22 , 11

promise函数

promise是一个ES5已经出现了 ES6直接给出标准
promise是一个构造函数 创建了一个数据容器
map set arr object 都是数据容器,被动产生数据 给他添加数据
promise主动产生 不用给他添加数据 而是它自己产生数据

我们先来创建一个promise对象

var p1 = new Promise()

那么这里的p1什么? p1 是一个对象

对象的功能是什么呢? 是保存数据的,比如数组保存了数据以后 用下标来取,比如普通对象保存数据,用属性名取值 ,Map也是特殊对象保存了数据 用get方法来取值,set也是特殊对象保存了数据,用遍历器来取值

p1也是一个特殊对象,它内部的数据是自己产生的,而不是从外界保存进去的,它的取值使用then方法来取

var p1 = new  Promise(function(n1,n2){
var n = Math.random();
n1(n); // n1调用了,就代表p1产生了数据
} )
// p1数据容器取数据用then函数,是一个异步函数
var re = p1.then(function(data){
console.log(data,111);
return 200;
} )
console.log(222);
// 取数据就是传入回调函数来取 当上面运行完就会把值传入下面这个函数
// 当n1 调用完了之后就会触发下面这个函数的执行
re.then((data) => {console.log(data,222)});
		

n1 是一个函数,n2 也是一个函数 ,函数的使用直接调用就好了
这个跟return是一样的只能产生n1或者n2的数据,如果两个都在那么谁先运行完了就停了

n1(n); 运行表示p1数据容器内部产生了数据:n,n1 调用代表触发了p1对象内部产生的数据
在业务中n1触发代表产生正常的数据,n2代表触发错误的数据

then函数的返回值,是一个新的promise对象

关于then传入的回调函数的返回值:
如果返回值是一个promise对象那么就是它
如果返回值不是一个promise对象,那么会把函数的结果包装为一个生成数据了的premise对象

promise ==> promise函数不是异步函数,非阻塞函数,then函数才是一个异步非阻塞函数
then里面第一个函数是取出正确的数据,第二个函数是取出错误的数据
用throw来抛出错误,下面进行捕获也是可以的
p1这个promise对象有两个函数可以使用then函数取值,还可以使用catch方法可以捕获错误信息

// 为什么要用catch呢?
// 这样就可以很方便接收错误数据了,有错误数据抛出却不接收就会报错
p1.then(function(data) {
	console.log(data, 11);
		}).catch(function(e) {
	console.log(typeof e, e);
})
// 这里的catch触发必须是要么n2调用 要么throw抛出,就算是创建一个错误对象传给n1也不会触发catch的

任务的队列分类

任务指的就是js代码中的运行的代码
fn() 代表了fn任务的运行 脚本的运行也是一个任务,计时器的运行也是一个任务 promise也是一个任务
任务分为同步的任务 异步的任务

我们先来看同步任务
下面三个就是同步任务,一个一个的执行就叫同步任务

function fn(){}
var a = new Array()
var b = fn()

异步任务,then括号里的写成fn()就是我们在调函数,写成fn就是计时器内部在调用函数

setTimeout(fn, 1000);
p1.then(fn);
console.log(123);

异步任务的队列优先级:异步宏任务先执行,然后再执行异步微任务
宏:脚本是一个宏任务

脚本运行 执行第一个宏任务:

  1. 先执行同步任务
  2. 添加新的宏任务到队列中,添加这一轮的异步微任务
  3. 执行异步微任务
// 先执行同步任务,在执行宏任务,然后执行宏任务里面的微任务,执行完后就可以执行下一个宏任务了
// 这里的setTimeout是宏任务,then是微任务
console.log(4);
setTimeout(() => {
	console.log(1);
}, 0);
setTimeout(() => {
	console.log(2);
	setTimeout(() => {
		console.log(6);
	}, 200);
}, 0);
var p1 = new Promise(n1, n2) => {
	n1(1000);
}
p1.then(() => {
	console.log(3);
})
console.log(5);
// 执行结果是 4 5 3 1 2 6

还有一个题可以自己去看看

setTimeout(() => {
console.log(0);
});
new Promise(resolve => {
	console.log(1);
	setTimeout(() => {
		resolve();
		var p1 = new Promise((n1, n2) => {
			n1(20)
		})
		p1.then(() => console.log(2));
		console.log(3);
	});
	// promise同步但是没打印,然后直接then微任务 
	new Promise((n1, n2) => {
		n1(20)
	}).then(() => console.log(4));
}).then(() => {
	console.log(5);
	var p2 = new Promise((n1, n2) => {
		n1(20)
	})
	p2.then(() => console.log(8));
	setTimeout(() => console.log(6));
});
console.log(7);
// 打印结果 1 7 4 0 3 5 2 8 6

事件循环

什么是事件循环呢?
事件循环:就是任务开启后,内部执行的时候可能会有新任务

先执行第一轮宏任务 (脚本)中的代码:同步 - 微任务 - 下一轮宏任务中的代码
宏任务中:同步 - 微任务 - 下一轮排队的宏任务
下一轮排队的宏任务中 执行同步 - 执行微任务 - 遇到宏任务继续排队 - 执行下轮排队的宏任务
下一轮排队的宏任务中:执行同步 - 执行微任务 = 遇到宏任务继续排队 - 执行下一轮排队的宏任务
下一轮排队的宏任务中:执行同步 - 执行微任务 = 遇到宏任务继续排队 - 执行下一轮排队的宏任务
这样就事件循环起来了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值