开课吧04期03
解决JS单线程的阻塞问题HTML5提出Web Worker标准,允许创建多个线程
同步异步是一种消息通知机制
- 同步可以理解成非阻塞(相当于并行),异步理解成阻塞(相当于串行),但不绝对
- 同步while(1)就阻塞了
- 异步会有回调函数或者返回值通知,不会等待,会去做其他事
- 同调就是「当发生 A 事件的时候调用 fA () 函数
- 任务队列中的都是已经完成的异步操作,而不是注册一个异步任务就会被放在任务队列中
关于同步、异步、回调 这篇很清楚:回调(callback)_zjpp2580369的博客-CSDN博客_回调
关于宏任务、微任务:掘金
如何理解process.nextTick()?强大的异步专家process.nextTick() - 简书
process.nextTick()比setTimeout()更精准的延迟调用
同步
三个1000的setTimeout会同时执行
alert()会阻塞其他打印
异步
setTimeout中的回调函数、递归
解决 打印222在setTimeout之后的问题
function fn(cb){
setTimeout(()=>{
console.log("111");
cb && cb();
},1000)
}
fn(function(){
console.log("222")。
})
解决同步异步不是同一个线程 无法从主线程获取异步的问题
https://www.jb51.net/article/173306.htm
Promise实例化有三种状态:
pending,resolve,reject 执行中,成功时,失败时
默认 pending(没有结果前的状态)
参数 resolve:fulfilled(火狐),reject
两个参数都是调用后出现
Promise提供then方法
then 两个参数(onresolved,onrejected)
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(“success”);
// reject(“error”); 两者只能有一个
},1000);
}
p.then(function(res){ //第一个参数 onresolved
console.log("成功“,res);
},function(err){ //第二个参数 onrejected,可省略
console.log("失败",err);
})
then的三种返回值:
1、then的回调 无返还时:默认返还resolved状态的promise对象
let p2 = p.then(function(){ } )
默认返回对象,出现链式,仍可调用then
p2.then();
2、then的回调 有返还时:返还的是非promise对象,默认还是promise对象 传参
let p2 = p.then(function(){
console.log(111);
} )
console.log(p2);
let p2 = p.then(function(){
console.log(111);
} ) . then(function(res){ //拿上面的参数
console.log(res); //返回111
} )
3、直接return Promise对象
let p2 = p.then(function(){
return new Promise((resolve)=>{
resolve();
});
} )
总结:三种返还的都是promise对象,可以一直调用then
请求图片 实现异步的三种方法:function回调、then、async
图片加载就是一个异步过程
Image是类,分别打印成功和失败
异步实现
Promise实现
.then().catch().then 链式操作更便于维护
catch有返还值,返还值参照then方法
ES7 async await 异步的同步写法(实现异步操作的同步化)
比如登录时,我们必须要在后台返回匹配成功的信息之后才能进行页面跳转
- async是Promise的语法糖
- 函数有等待时用await
- await后一定要加Promise 等待的标志:resolve
async function fn(){
await new Promise((reslove,reject)=>{ //await后面必须跟Promise
})
}
fn();
仍然按顺序走,执行resolve才执行下一个
视频中使用方块运动的例子:
async function fn() {
try {
await move(ele, "left", 200);
await move(ele, "top", 200);
await move(ele, "left", 0);
let res = await move(ele, "top", 0);
console.log(res);
} catch (err) {
console.log(err);
}
}
fn();
try catch 报错并不会阻止程序执行,只是打印出来
finally,catch六.Promise中finally,catch方法的实现 - 知乎
Promise的静态方法:resolve()、reject()、all()和race()五.Promise中静态方法的实现 - 知乎
Promise.resolve() 返还一个状态为resolve的Promise对象
Promise.reject()
同时执行all(常问)
Promise.all( [p1,p2,p3]).then( res=> console.log(res) ) //返回数组,有一个reject时报错
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('p1'), 100)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => reject('p2'), 500)
})
Promise.all([p1, p2]).then(rets => {
console.log(rets)
})
不管resolve还是reject都执行,但是按照时间先后顺序执行 谁执行的快就拿谁race(常问)
Promise.race( [p1,p2,p3]).then( res=> console.log(res) )
var p1 = new Promise(function(resolve) {
setTimeout(() => {
resolve("fulfilled");
}, 200);
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(() => {
reject("rejected");
}, 100);
});
Promise.race([p1, p2]).catch(function (reason) {
console.log(reason); //"rejected"
});
ES6躬行记(23)——Promise的静态方法和应用 - 知乎
异步异常处理:promise异步异常处理----async和await_Dean's-CSDN博客
对于方法async fn中出现的异步异常,不能用普通的try…catch…方法捕捉到异常,需要这样做:
- 把抛出异步异常的方法用
promise
包裹 - 用
await
获取fn
的返回值:await fn()
,await
作用是计算表达式 try...catch
捕获异常
async function fn() {
try {
console.log(await fn2())
} catch(error) {
console.log('error')
}
}
async function fn2() {
await setTimeout(() => {
throw new Error('error')
}, 1000)
}
fn()中捕捉不到error,用promise包装一下:
async function fn() {
try {
console.log(await fn2())
} catch(error) {
console.log('error')
}
}
function fn2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('error')
}, 1000)
})
}
promise为reject时候,捕捉到异常
async await原理是什么?
原理是迭代
迭代协议:规定迭代与实现的逻辑
迭代器:具体的迭代实现逻辑(实现迭代协议)
数组内部有迭代器iterator
迭代对象:可被迭代对象(实现迭代器的对象) 数组
迭代语句:
for ... in
for ... of (obj不是可迭代对象)
方法实现for ... of迭代对象:(固定写法)
let obj = { a:1,b:2,c:3};
obj [Symbol.iterator] = function( ){ //iterator方法返回值必须是对象
//迭代协议 可自定义
// let value = Object.value(obj);
let keys = Object.keys(obj);
let index = 0;
return{
next(){
if(index >= keys.length){
return {
done: true }
}else{
return{
done:false,
//value: values [ index++ ] } //是否迭代完成
value: { key: keys [ index ] ,
value: obj [ key [ index++ ] ] }
}
}
}
}
for(let val of obj){ //相当于 obj [Symbol.iterator] ().next
console.log(val);
}
Generator 是 async await的前身(已经不用了)
function*fn( ){ // Generator函数固定写法
yield new Promise((resolve, reject)=>{ //yield定义next方法
setTimeout(()=>{
resolve(1);
}, 500)
});
yield new Promise((resolve, reject)=>{ //yield定义next方法
setTimeout(()=>{
resolve(2);
}, 500)
});
yield 3; //yield 1 2 3 可以直接for ... of调用
}
co( fn );
co( fn ){ //处理异步时封装let f = fn();
next(); //第一次没有传参
function next(data){
if ( ! f.next.done ){
f.next.value.then((info)=>{
console.log(info,data); //info是当前resolve的值,data是上一个的值
next(info);
})
}
}
}
EventLoop 事件循环机制掘金
主线程形成一个执行栈
new Promise是同步任务
从promise、process.nextTick、setTimeout出发,谈谈Event Loop中的Job queue_liwusen的博客-CSDN博客_process.nexttick settimeouthttps://www.cnblogs.com/youxin/p/3354924.htmlsetTimeout和setInterval的异同https://www.cnblogs.com/youxin/p/3354924.html从promise、process.nextTick、setTimeout出发,谈谈Event Loop中的Job queue_liwusen的博客-CSDN博客_process.nexttick settimeout