Javascript递归承诺 [英] Javascript Recursive Promise

查看:63
本文介绍了Javascript递归承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a recursive function using Promises, but can't quite seem to get it right. I have working code without using promises, but it uses counters and global variables etc. and doesn't feel quite right, so I'm attempting a rewrite and also creating a module for reuse.

本质上,该函数应该是从Active Directory获取用户,然后以递归方式查找任何直接报告及其直接报告等等。

Essentially, the function is supposed to be getting a user from Active Directory and then recursively finding any direct reports and their direct reports and so on.

I已经使用了很多版本的函数,这是当前版本:

I've played with lots of versions of the function, this is the current one:

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));
    });
}

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

The getAccessTokenPromise function performs a request for an access token and returns a promise for that. The makeRequest function again just makes an https request for the user and their reports and returns a json object with the results as a Promise.

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

Any thoughts greatly received. Many thanks. D.

推荐答案

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

To make recursion work with promises, you generally want to chain all the recursive promises to their callers. To do that, you MUST return any promises from your .then() handlers so that they are chained to the originals. This also tends to eliminate your promise anti-pattern of wrapping an existing promise with a manually created promise which is fraught with problems. Here's one way of doing that:

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);
            }));
        }
    });
}

所做的更改:


  1. 在getAccessTokenPromise()之前添加 return ,以便我们返回初始承诺。这也让我们消除了新Promise()以及反模式中涉及的所有手动拒绝和解析。

  1. Add return before getAccessTokenPromise() so we're returning the initial promise. This also lets us eliminate the new Promise() and all the manual reject and resolve that was involved in the anti-pattern.

在递归 loadReports()之前添加 return 。必须这样做是为了允许 .map()在将其传递给 Promise.all()

Add return before the recursive loadReports(). This has to be done to allow the .map() to collect that promise before it passed it to Promise.all().

Promise.all()之前添加返回 / code>所以它被链接到原始的承诺链。

Add return before the Promise.all() so it is chained to the original promise chain.






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


You will have to make sure that you can never get any sort of circularity in the database data (an error in the DB that creates a circular list of reports). A reports to B, B reports to C, C reports to A because if you did have this, then this code would go on forever and never complete (probably eventually exhausting some system resource).

如果这是我的代码,我可能会创建一个包含数据库中访问过的所有人的集合,并拒绝调用 loadReports()关于我们以前访问过的任何人。这样可以避免循环。如果你看到那个条件,你可能还想要 log(),因为它可能是数据库错误/损坏。

If this were my code, I might create a Set of all people visited in the database as I go and refuse to call loadReports() on any person who we'd already visited before. This would make it safe from circularity. You would probably also want to log() if you saw that condition because it would probably be a database error/corruption.

这篇关于Javascript递归承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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