frontend-interview
frontend-interview copied to clipboard
解释一下Co函数的作用,如何编写Co函数
co 函数是帮助我们自动调用 generator,不必自己写 gen.next()。主要是通过 thunk 或者 promise 实现,4.x 之后改成使用 promise。如果是 thunk 的版本的话,主要是将封装好的 next 作为 thunk 的回调。promise 版本里面,因为 yield 后面跟的是 promise,通过 then 和内部会执行 next 的自定义的 onFulfilled 和 onRejected。
function co(gen) {
return new Promise((resolve, reject) => {
const g = gen()
onFulfilled()
function onFulfilled(val) {
let ret
try {
ret = g.next(val)
} catch(e) {
reject(e)
}
next(ret)
}
function onRejected(val) {
let ret
try {
ret = g.next()
} catch (e) {
reject(e)
}
next(ret)
}
function next({ value, done }) {
if (done) return resolve(value)
// 4.x 版本转成 promise,如果是对象和数组会使用 Promise.all,不转基础数据
const v = toPromise(value)
if (v instanceof Promise) {
v.then(onFulfilled, onRejected)
} else {
onRejected('error')
}
}
})
}
function* gen() {
try{
yield Promise.reject(1)
} catch(e) {
// throw 抛出的错 1
}
// 判断 generator 的方式有 gen.constructor.toString 或者 gen.constructor.name,
// 内部转Promise的时候递归 co 就可以,都是返回 promise
yield function* foo() {}
// 遍历对象转 promise,可能递归,输出一个数组
yield {}
// 每个元素转 promise 是个可能会发生递归,然后 Promise.all
yield []
// 转化的时候包装一层 promise,内部调用 thunk 并将 resolve 写在回调里面。
yield thunk
}
co(gen).then(res => {
console.log(res)
})
- co 函数的作用是让 Generator 函数的自动执行。
- 编写: ` function co(gen) { var ctx = this;
return new Promise(function(resolve, reject) { if (typeof gen === 'function') gen = gen.call(ctx); if (!gen || typeof gen.next !== 'function') return resolve(gen);
onFulfilled();
function onFulfilled(res) {
var ret;
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
next(ret);
}
});
}
function next(ret) { if (ret.done) return resolve(ret.value); var value = toPromise.call(ctx, ret.value); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); } }); `
co 函数可以帮助我们自动执行 Generator 函数。 使用 co 的前提条件是,Generator 函数的 yield 命令后面,只能是 Thunk 函数或 Promise 对象。 原理就是判断 Generator 函数调用结果的 done 是否为 true,如果不为 true, 则拿到 value 继续调用 .then 处理下一步 next。
co是Generator函数的自动执行器。它会返回一个Promise值。
其实就是递归的去调用Genertor函数返回值的next方法,让函数内部指针下移。
代码实现
function co(it){
return new Promise((resolve,reject)=>{
function next(data){
let {value,done} = it.next(data);
if(!done){
Promise.resolve(value).then(data=>{
next(data);
},reject)
}else{
resolve(value);
}
}
next();
});
}
co的作用就是让generator函数自动执行,也就是当yield表达式有结果的时候,自动执行后边的操作,相当于继续调用next()方法。 co的关键点: 1、co返回的是一个promise; 2、利用promise自动执行generator; 3、可传入多个参数。
function co(gen) {
gen = gen()
//可传入多个参数
// var args = Array.prototype.slice.call(arguments, 1)
// gen = gen.bind(args)()
return new Promise((resolve,reject) => {
onFulfilled()
function onFulfilled(res) {
var ret = gen.next(res)
next(ret)
}
function next(res) {
if (res.done) return resolve(res.value)
// 自动执行
Promise.resolve(res.value).then( e => {
onFulfilled(e)
} )
}
})
}
- Co函数可以自动执行Generator函数
- Generator函数是异步操作的容器,需要调用next()恢复执行,需要实现自动执行需要上一次的异步结果能自动交回执行结果,因此有两种方式,
- 将异步操作包装成Thunk函数
- Promise
- Co函数内的自动执行函数会递归的调用直至next.done为true
- Co函数可以自动执行Generator函数
- Co函数可以递归的去调用Genertor函数返回值的next方法
- Co函数递归出口调用结果为 done
- Co函数返回一个Promise
- co 函数可以帮助我们自动执行 Generator 函数。
- 使用 co 的前提条件是,Generator 函数的 yield 命令后面,只能是 Thunk 函数或 Promise 对象。
- 原理就是判断 Generator 函数调用结果的 done 是否为 true,如果不为 true, 则拿到 value 继续调用 .then 处理下一步 next。
Co函数的作用,如何编写Co函数?
[co 函数库] 是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行。
使用 co 的前提条件是:Generator 函数的 yield 命令后面,只能是 Thunk 函数或 Promise 对象。
Generator 函数就是一个异步操作的容器。它的自动执行需要一种机制,当异步操作有了结果,能够自动交回执行权。
两种方法可以做到这一点:
- 回调函数。将异步操作包装成 Thunk 函数,在回调函数里面交回执行权。
- Promise 对象。将异步操作包装成 Promise 对象,用 then 方法交回执行权。
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen); // gen 是一个 Generator 函数
只要 Generator 函数还没执行到最后一步,next 函数就递归调用,从而实现自动执行。
co
是generator
函数的执行器,本质就是将next
执行权交由co
,它的作用就是自动调用next,
不需要我们自己去调用了
co的使用条件是generator函数 yield关键字
后只能是thunk函数
或者promise对象
那么如何去编写co函数
co函数本质是递归调用generator函数的next方式
所以编写co函数关键是判断每次执行next后的done值,根据done值觉得是否继续调用next, 这就是递归终止的条件
co
函数能够让 Generator
函数的自动执行,只要将 Generator
函数传入 co
函数,如:co(gen)
,co
函数返回一个 Promise 对象,可以用 then
方法添加回调函数
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(gen);
- co函数的作用 co函数可以自动执行Generator函数, Generator 函数只要传入 co 函数,就会自动执行。co 函数返回一个 Promise 对象,因此可以用 then 方法添加回调函数
- co 函数库的原理 为什么 co 可以自动执行 Generator 函数,Generator 函数就是一个异步操作的容器。它的自动执行需要一种机制,当异步操作有了结果,能够自动交回执行权。两种方法可以做到这一点 (1)回调函数。将异步操作包装成 Thunk 函数,在回调函数里面交回执行权。 (2)Promise 对象。将异步操作包装成 Promise 对象,用 then 方法交回执行权。 co 函数库其实就是将两种自动执行器(Thunk 函数和 Promise 对象),包装成一个库。使用 co 的前提条件是,Generator 函数的 yield 命令后面,只能是 Thunk 函数或 Promise 对象。