学习异步与Promise
同步与异步
同步(Synchronous)
同步可以直接拿到结果
简单的例子来说,同步就是在学校食堂吃饭,必须要排队打饭,在打到饭之前都不能离开去做其他事情。
用计算机的语言来解释就是同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。是一种线性执行的方式,执行的流程不能跨越。
异步(Asynchronous)
异步不能直接拿到结果,需要后续通过轮询或者回调的方法来得到结果
简单的例子来说,异步就是在网红饭店改善生活时,可以在在手机上取号后,就去逛街买奶茶干其他的事情,当手机上通知到你时再去就餐。
用计算机的语言来解释只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。是一种并行处理的方式。
JS是单线程的
学习Java时,Java中可以通过开启多线程来完成异步操作,但是JS是单线程的是怎样执行异步任务的呢?
JS是单线程的,是指在浏览器的JS引擎中负责解释和执行JavaScript代码的线程只有一个,所以我们所写的JS代码在JS引擎中都是排队(同步)执行的。但很多时候关于I/O设备的操作要比闪电般的JS引擎慢很多,比如鼠标键盘的操作、网络请求……JS引擎中遇到这样的任务就很容易导致后续其他任务阻塞的问题,所以需要异步执行JS代码中的这些任务,咋异步呢?
多线程的浏览器就来帮忙啦,直接甩出三个大招(API),分别是 DOM Binding(DOM绑定)、network(网络请求)、timer(定时器)模块。
如果JS代码中的任务是属于这三个模块,浏览器就会判断它为异步任务,然后JS引擎中一遇到异步任务,浏览器就会把异步任务相关回调添加到任务队列中(异步任务必须要有回调函数),等待主线程的任务执行完毕,再执行任务队列中的任务。
这种运行机制称为Event Loop(事件循环)
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
Promise
上面介绍了JS中需要异步,Promise就是ES6中异步编程的一种解决方案
为什么需要Promise?
以往我都使用jQuery封装的Ajax来发送网络请求,当网络请求十分复杂时就会出现回调地狱
上图中回调得到的数据很容易混淆,且代码就十分难看且不容易维护,所以我们需要更优雅的方式来进行异步操作
Promise的使用
第一步
创建一个promise对象、可以使用new
来调用Promise
的构造器来进行实例化
return new Promise((resolve,reject)=>{
// 异步处理
// 处理结束后、调用resolve 或 reject
})
-
任务成功时调用
resolve(成功)
任务失败时调用reject(失败)
-
resolve 和 reject 都只接受一个参数
第二步
第一步构造出来的promise对象,含有一个 .then() 函数属性使用promise.then()
实例方法,设置其值在 resolve(成功) / reject(失败)时调用的回调函数
promise.then(onFulfilled, onRejected)
-
resolve(成功)时
onFulfilled
会被调用 -
reject(失败)时
onRejected
会被调用
举例
使用promise来发送网络请求
function getURL(URL) {
return new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', URL, true);
req.onload = function () {
if (req.status === 200) {
resolve(req.responseText);
} else {
reject(req.statusText));
}
};
req.onerror = function () {
reject(req.statusText));
};
req.send();
});
}
var URL = "http://xxx";
getURL(URL).then(function onFulfilled(value){
console.log(value);
},function onRejected(error){
console.log(error);
});
Promise还有更高级的用法,链式调用等等,以后在进行总结~