thunk
Thunk 函数:传入 thunk 函数的参数是另一个函数,thunk 函数返回值也是一个函数,执行这个函数,实际上是执行了传入 thunk 函数的那个函数
eg:
function add(a,b){
return a+b
}
function thunk(fn){
return function(){
let args = Array.prototype.slice.call(arguments)
fn.apply(this,args)
}
}
let exact = thunk(add)
exact(1,2)
add 函数可以是一个基础函数, thunk 函数中可以根据不同的需求对函数进行修改。
async await
async await 函数是对异步操作的最大集成,在 async await 之前,使用 Generator 函数对异步操作同步处理,写法是这样:
function *fun(){
yield `第一个异步操作`
yield `第二个异步操作`
return "something"
}
Generator 函数是一个状态机,封装了的多个内部状态,也可以说它是一个遍历器对象生成函数,因为执行这个函数会返回一个遍历器对象(指向内部状态的指针对象);遍历器对象里面保存着 Generator 函数当前的状态;因此要访问 Generator 函数的每个状态(执行完所有的异步方法)需要手动调用遍历器对象的 next() 方法或者使用 co 函数库作为 Generator 函数的执行器,或者自己实现一个执行器,使 Generator 函数能够自动执行。
也就是说虽然 Generator 函数可以避免 callback hell,但是也有一些附加的步骤,且要求 yield 表达式后面的表达式必须是 promise 或者是 thunk 函数。
使用 async await 函数的写法大概是这样的:
async function fn(){
await `第一个异步函数`
await `第二个异步函数`
return "something"
}
看起来就像是 Generator 函数的 * 换成了 async 关键字、yield 表达式换成了 await 表达式。但是 async 函数会自动依次执行,不需要执行器,且: async 函数返回的是一个 promise 对象。
async 关键字表示这个函数里面有需要异步执行的函数,使用 async 标记的函数类似于又把函数包了一层:
eg:
async function fn(){
...一些代码...
}
相当于:
function fn(
return spawn(function* (){
})
)
这里的 spawn 函数的实现类似于下面这样:
function spawn(fn){
return new Promise(function(resolve,reject){
let g = fn()// 获得生成器函数的遍历器对象
function next(fnext){
let fResult;
try{
fResult = fnext()
}catch(e) {
return reject(e)
}
if(fResult.done) return resolve(fResult.value);
Promise.resolve(fResult.value).then(function(v){
next(()=>g.next(v))
},function(e){// Promise.resolve 相当于 new Promise(resolve=>resolve()),不会有 reject 的情况,所以这里是捕获fResult.value执行的时候出现的异常并做处理
next(()=>g.throw(e))
})}
next(()=>g.next())
})
}
所以按照我的理解:
await abc()
//... 后面的表达式
相当于:
Promise.resolve(abc()).then("后面的表达式")
参考: