Javascript递归承诺

Dar*_*ren 8 javascript recursion promise ecmascript-6 es6-promise

我正在尝试使用Promises创建一个递归函数,但似乎无法正确使用它.我有工作代码而不使用promises,但它使用计数器和全局变量等,并且感觉不太正确,所以我正在尝试重写并创建一个模块以供重用.

本质上,该功能应该是从Active Directory获取用户,然后递归查找任何直接报告及其直接报告等.

我玩过很多版本的函数,这是当前版本:

function loadReports(personEmail, list) {
    return new Promise((resolve, reject) => {
        getAccessTokenPromise()
            .then(access_token => {
                list.push(personEmail);
                return makeRequest(personEmail, access_token);
            }).then(result => {
                if (result.value.length > 0) {
                    Promise.all(result.value.map(person => {
                        loadReports(person.userPrincipalName, list);
                    })).then(resolve());
                } else {
                    resolve();
                }
            })
            .catch(e => reject(e));
    });
}
Run Code Online (Sandbox Code Playgroud)

getAccessTokenPromise函数执行访问令牌的请求并返回对此的承诺.该makeRequest函数再次为用户及其报告发出https请求,并返回一个json对象,其结果为Promise.

任何想法都很受欢迎.非常感谢.D.

jfr*_*d00 6

要使递归与promises一起工作,您通常希望将所有递归承诺链接到其调用者.要做到这一点,你必须从你的.then()处理程序返回任何承诺,以便它们被链接到原件.这也倾向于消除你的承诺反模式包装现有的承诺与手动创建的承诺充满问题.这是一种方法:

function loadReports(personEmail, list) {
    return getAccessTokenPromise().then(access_token => {
        list.push(personEmail);
        return makeRequest(personEmail, access_token);
    }).then(result => {
        if (result.value.length > 0) {
            return Promise.all(result.value.map(person => {
                return loadReports(person.userPrincipalName, list);
            }));
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

做出的改变:

  1. return在getAccessTokenPromise()之前添加,所以我们返回初始的promise.这也让我们消除new Promise()了反模式中涉及的所有手动拒绝和解决方法.

  2. return在递归之前添加loadReports().必须这样做才能.map()在传递之前收集该承诺Promise.all().

  3. return在之前添加,Promise.all()因此它被链接到原始的promise链.


您必须确保您永远不会在数据库数据中获得任何类型的循环(DB中创建循环报告列表的错误).报告给B,B向C报告,C向A报告,因为如果你确实有这个,那么这段代码将永远存在并且永远不会完成(可能最终耗尽一些系统资源).

如果这是我的代码,我可能会在我去的时候创建一个在数据库中访问过的所有人的集合,拒绝呼叫loadReports()我们之前已经访问过的任何人.这样可以避免循环.log()如果您看到这种情况,您可能也会想要,因为它可能是数据库错误/损坏.