代码异步和非阻塞 Asynchronous JS
const img = document.querySelector('.dog');
// 这一行是异步的,假设图片很大的话在“后台”加载完成再显示会提高用户体验
img.src = 'dog.jpg';
// 只有当图片加载完成才会抛出一个load事件,回调函数被调用,加入一个css效果。
// addEventListener本身不会导致代码异步执行,只是图片在后台异步加载
img.addEventListener('load', function() {
img.classList.add('fadeIn');
});
p.style.width = '300px';
AJAX: Asynchronous JS And XML(一种过去常用的传输数据的格式), 允许我们用异步的方式去和远程web服务器进行交流。
Promises (ES6)
定义:一个对象,用于存放一个异步操作未来传回的值(container / placeholder)。
用promise的好处:chain promises可以完成一系列的异步操作.
特点:因为跟异步操作有关,所以是时间敏感的,promise的状态会随着时间变化而改变,但一旦变成settled的状态就不可被更改了。一般都只用消费promise对象,例如fetch返回一个promise,但也有时候会需要自己build a new promise。
- consuming promises
- then() : 只会在promise fulfilled的时候被调用,得到的是resolved value,如果没有resolved value就会
() => {...}。
response.json() :
- 所有从fetch函数返回的response对象【所有resolved value】均可调用json方法,这个response已经是一个resolved value。
- 这个json方法也是异步方法,会返回一个新的promise, 所以可以接着调用then()方法。
const getCountryData = function (country) {
// Country 1
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then(response => {
return response.json();
})
.then(data => {
renderCountry(data[0]);
const neighbour = data[0].borders[0];
if (!neighbour) return;
// Country 2
return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`);
// 不要直接在fetch后面.then()!!!! => 这样又回到了callback hell(在callback中定义callback)
})
.then(response => {
return response.json();
})
.then(data => {
renderCountry(data, 'neighbour');
}));
};
- 处理Rejected Promises
fetch()唯一reject的情况:用户网络连接断开的情况下发请求。
-
方法一:then()中传递第二个callback fn。(第一个fn用于处理fuffilled promise, 第二个处理rejected)
- 比如
err => alert(err)
- 比如
-
方法二:在链的最末端
.catch(err => alert(err)),可以处理发生在promise链中的任何错误。
finally() 方法有效的原因是then() / catch() 方法都会自动返回一个promise对象。
页面404的话fetch的promise仍会得到fulfilled的状态,所以无法用catch处理。
-Throwing Errors Manually (处理类似404而不是网络断连接的error)
fetch('http://localhost:5500/root').then(response => {
console.log(response);
// 一些真正想要的错误信息
// 通过构造函数创建new error, throw会像return一样立马从当前的函数返回
// promise会立即变成reject状态,这个rejection会沿着promise链向下传播到catch()函数
if (!response.ok) throw new Error('Country not found');
});
-事件循环/ callback queue / microtasks queue
因为微服务的优先级高于callback fn,所以已经执行的微服务如果源源不断地产生新的微服务的话,就会产生callback queue中任务饥饿的情况。以及如果microtask需要花费较长时间才完成的话,普通callback例如setTimeout注册的回调函数不一定就在指定几秒之后就执行,有延迟。
例子:
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(function() {
console.log('promise1');
})
.then(function() {
console.log('promise2');
});
console.log('script end');
输出:
script start
script end
promise1
promise2
setTimeout
-自己build Promise
// 给Promise这个构造函数传入的是一个`executor`执行函数
const lotteryPromise = new Promise(function(resolve, reject) {
// 假设彩票有50%的中奖几率
if (Math.random() >= 0.5) {
// 赢了彩票=>一个fulfilled promise,实现了的承诺
// 调用resolve函数,将promise设置为fulfilled
// 设置传入的东西为resolved value
resolve("YOU WIN");
} else {
// 会被catch接收
reject("YOU LOST YOUR MONEY");
}
})
// 向then方法传入的是resolved value
lotteryPromise.then(res => console.log(res)).catch(err => console.error(err));
zzzz这个人活动快结束了才开始写笔记呜呜呜( ´・・)ノ(._.`)