如何从JavaScript中的递归生成器函数返回? [英] How do I return from a recursive generator function in JavaScript?

查看:98
本文介绍了如何从JavaScript中的递归生成器函数返回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩一个递归生成器函数,该函数异步返回值.我正在使用协程包装函数来调用它.代码和下面的JSBin:

I'm playing around with a recursive generator function that returns values asynchronously. I'm using a coroutine wrapper function to call it. Code and JSBin below:

http://jsbin.com/nuyovay/edit?js,console

let log = console.log.bind(console);
let err = console.error.bind(console);

function coroutine(generatorFn){
    return function co() {
        let generator = generatorFn.apply(this, arguments);

        function handle(result) {
            console.log(result);
            if (result.done) {
                return Promise.resolve(result.value);
            }
            return Promise.resolve(result.value)
                .then(
                    res => handle(generator.next(res)),
                    err => handle(generator.throw(err))
                );
        }

        try {
            return handle(generator.next());
        } catch (err) {
            return Promise.reject(err);
        }
    };
}

function sleep(dur) {
    return new Promise(res => {
        setTimeout(() => { res() }, dur);
    });
}

function* recurse(limit = 5, count = 0) {   
    if(count < limit) {
        yield sleep(100).then(() => Promise.resolve(++count));
        yield* recurse(limit, count);
    }
    else {
        return count;
    }
}

let test = coroutine(recurse);

test().then(log).catch(err);

运行此命令将返回:

Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
Object {value: Promise, done: false}
// `value` should be 5
Object {value: undefined, done: true}

生成器的最终return为何是undefined?当我将上述内容与bluebird的Promise.coroutine结合使用时,我得到的结果是相同的.我是否缺少有关递归生成器的基本知识?如何将其发送到{ value: 5, done: true }?

How come the final return from the generator is undefined? When I adapt the above for use with bluebird's Promise.coroutine, I get the same result. Am I missing something fundamental about recursive generators? How do I get it to { value: 5, done: true }?

推荐答案

问题是您要返回count,但是您要在父生成器中返回它.与委托生成器中的yield不同,return不会通过委托链自动生成.

The issue is that you are returning count, but you're returning it in the parent generator. Unlike yield in delegated generators, return is not yielded back up through the delegation chain automatically.

如果要获取委托生成器的return值,则必须直接在父生成器中分配它:

If you want to get the return value of a delegated generator, you have to assign it directly in the parent generator:

let returnValue = yield* recurse(limit, count);

由于您使用的是递归"生成器(多个委派级别),因此您需要重复该过程并在每个委派级别返回值:

Since you're using "recursive" generators (multiple levels of delegation), you would need to repeat the process and return the value at every level of delegation:

function* recurse(limit = 5, count = 0) {   
    if(count < limit) {
        yield sleep(100).then(() => Promise.resolve(++count));
        let result = yield* recurse(limit, count); // save the return value
        return result; // return it to the parent
    }
    else {
        return count;
    }
}

这篇关于如何从JavaScript中的递归生成器函数返回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆