前端的异步流程
传统的原生异步的两种解决方法: 回调函数和事件
异步流程工具的使用
1.1 promise
-
Promise 是异步编程的一种解决方案,比传统的解决方案回调函数和事件更合理和更强大。
-
Promise 由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise
-
所谓Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果。
-
Promise从语法上来说,它是一个对象,从它那里可以获取异步操作的消息。
-
Promise 对象的状态不受外界影响
-
Promise 对象的三种状态:
- pending:进行中
- fulfilled :已经成功
- rejected 已经失败
-
Promise对象的状态改变,只有两种可能:
- 从pending变为fulfilled
- 从pending变为rejected。
- 这两种情况只要发生,状态就凝固了,不会再变了,这时就称为resolved(已定型)
-
Promise.all和Promise.race的使用
- Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的
- Promise.race数组里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态
const p1 = new Promise( ( resolve,reject ) => {
resolve( '任务一' )
}).then ( data => {
console.log( data )
})
const p3 = new Promise( ( resolve,reject ) => {
setTimeout( () => {
resolve( '任务三' )
},3000)
}).then ( data => {
console.log( data )
})
const p2 = new Promise( ( resolve,reject ) => {
setTimeout( () => {
resolve( '任务二' )
},2000)
}).then ( data => {
console.log( data )
})
console.log( '主线程任务' )
//Promise.all( [taskOne,taskTwo,taskThree],() => {
// })
//主线程任务
//任务一
//任务三
//任务二
Promise.race( [taskOne,taskTwo,taskThree],() => {
})
//主线程任务
//任务一
//任务三
//任务二
1.2 es6——generator函数
- 在function关键字后面加一个 * 这样定义的函数就叫做generator函数
function *fn () {}
-
generator函数通过 yield 关键字来定义任务
-
generator函数通过 fn().next() 来执行任务
- value表示yield关键字后任务执行的结果
- done表示当前定义的所有的任务是否执行完成的一个状态
-
理解:多任务的定义,多任务执行
- 让自己定义的多个任务依次执行,上一个任务如果没有完成,下一个任务就不会开始
function * fn () {
yield '任务一'
yield '任务二'
return '任务'
}
const a = fn();
console.log( a.next() ); // { value: '任务一',done: false }
console.log( a.next() );//{ value: '任务二',done: false }
console.log( a.next() );//{ value: '任务', done: true }
console.log( '主线程任务' );// 主线程任务
1.3 es6/7——async 函数
async函数由es6提供,配合关键字 awai t使用;await 表示等待,任务一执行结束之后,才会执行任务二
async function fn () {
const result = await '任务一'
console.log( result )
console.log( '任务二' )
}
fn()
// 任务一
//任务二
1.4 node.js中的 nextTick、setImmudiate
-
nextTick()的回调函数执行的优先级要高于setImmediate()。
-
process.nextTick()属于idle观察者,setImmediate()属于check观察者。 在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者。
- nextTick > 回调函数 > setImmediate
-
在具体实现上,process.nextTick()的回调函数保存在一个数组中,setImmediate()的结果则是保存在链表中。
-
在行为上,process.nextTick()在每轮循环中会将数组中的回调函数全部执行完。而setImmediate()在每轮循环中执行链表中的一个回调函数.
//加入2个nextTick()的回调函数
process.nextTick(function(){
console.log("nextTick延迟执行A");
});
process.nextTick(function(){
console.log("nextTick延迟执行B");
setImmediate(function(){
console.log("setImmediate延迟执行C");
});
process.nextTick(function(){
console.log("nextTick延迟执行D");
});
});
//加入两个setImmediate()回调函数
setImmediate(function(){
console.log("setImmediate延迟执行E");
process.nextTick(function(){
console.log("强势插入F");
});
setImmediate(function(){
console.log("setImmediate延迟执行G");
});
});
setImmediate(function(){
console.log("setImmediate延迟执行H");
process.nextTick(function(){
console.log("强势插入I");
});
process.nextTick(function(){
console.log("强势插入J");
});
setImmediate(function(){
console.log("setImmediate延迟执行K");
});
});
console.log("正常执行L");
//正常执行L
//nextTick延迟执行A
//nextTick延迟执行B
//nextTick延迟执行D
//setImmediate延迟执行E
//强势插入F
//setImmediate延迟执行H
//强势插入I
//强势插入J
//setImmediate延迟执行C
//setImmediate延迟执行G
//setImmediate延迟执行K
- 轮询: 一个事件往复执行,那么每一次执行完成,我们就认为是一个轮询
事件轮询前,我们使用nextTick
事件轮询后,我们使用setImmediate
1.5 第三方的 async.js 库
功能:
- 可以实现异步
- 串行series和并行parallel
const async = require( 'async' )
//series
async.series({
one: function ( callback ) {
setTimeout( function () {
callback( null, 1)
},200)
},
two: function ( callback ) {
setTimeout( function () {
callback ( null , 2 )
},100)
}
}, function ( error , results ) {
console.log( 'series',results )
})
console.log( '主线程' )
//parallel
async.parallel({
one: function ( callback ) {
setTimeout( function () {
callback( null, 1)
},200)
},
two: function ( callback ) {
setTimeout( function () {
callback ( null , 2 )
},100)
}
}, function ( error , results ) {
console.log( 'parallel',results )
})
//主线程
//parallel { two: 2, one: 1 }
//series { one: 1, two: 2 }
参考资料
-
Promise:https://blog.csdn.net/MrJavaweb/article/details/79475949
-
Async-await:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function
-
Node.js 中的nextTick()和setimmediate():https://www.cnblogs.com/5ishare/p/5268273.html
总结
异步流程的任务是放在异步队列中的,异步队列只有在主线程执行完之后采取执行