【问题标题】:How do I return a Promise from a loop in NodeJS?如何从 NodeJS 的循环中返回 Promise?
【发布时间】:2017-08-01 01:58:52
【问题描述】:

我需要建立map_of_uuid_ids_and_field_names_to_an_array_of_field_values

我需要在循环完成循环后返回这个对象。如何?

现在我的代码挂在这个循环的内部。我看了看,发现内部的“then()”语句没有“return”语句。但是,当我需要循环代码时,我怎么能在那里放一个 return 语句呢?如何从这个内部循环返回一个 Promise?

function get_map_of_uuid_ids_and_field_names_to_an_array_of_field_values(string_from_api_call, api_key_whose_name_should_match_the_name_of_a_database_field) {

    return new Promise(function(resolve, reject){

        var map_of_uuid_ids_and_field_names_to_an_array_of_field_values = {};
        sanitized_string_from_api_call = database_queries.sanitize_string(string_from_api_call);


        // 2017-07-10 -- this fixes:
        // TypeError: Cannot read property 'split' of null,   at get_map_of_uuid_ids_and_field_names_to_an_array_of_field_values (/home/ec2-user/daemons/deduplication_api/v9/dupe-res/actions.js:456:82)
        if (sanitized_string_from_api_call) {

            var array_of_words_from_string_from_api_call = sanitized_string_from_api_call.split(/\s+/);

            for (var k in array_of_words_from_string_from_api_call) {
                var word = array_of_words_from_string_from_api_call[k];

                // 2017-02-27 -- for the sake of performance, we skip over any string of 2 letters or less.
                // This means headquarters_country_code and headquarters_state_code need special handling.
                if (word.length > 2) {

                    return database_queries.get_map_of_type_of_profile_and_profile_id_pointing_to_document(word)
                        .then(function(map_of_type_of_profile_and_profile_id_pointing_to_document) {

                            if (map_of_type_of_profile_and_profile_id_pointing_to_document) {

                                map_of_uuid_ids_and_field_names_to_an_array_of_field_values = merge_objects(map_of_uuid_ids_and_field_names_to_an_array_of_field_values, transform_map_of_profile_type_and_profile_id_to_map_of_uuid_to_documents(map_of_type_of_profile_and_profile_id_pointing_to_document));

                            }
                        });
                }   
            }

        } else {
            console.log("the string value was null when api_key_whose_name_should_match_the_name_of_a_database_field was : " + api_key_whose_name_should_match_the_name_of_a_database_field); 
        }

        return map_of_uuid_ids_and_field_names_to_an_array_of_field_values;
    });
}

【问题讨论】:

  • 长名字到底是怎么回事?!
  • 如果它是异步的,你就不能真正返回。
  • 这是一个有趣的问题:)
  • 另外,您应该重新评估您的命名策略。明确变量名是好的,但这是越界了。

标签: node.js promise


【解决方案1】:

首先,您不能直接从使用异步操作获取结果的函数返回结果。您可以返回一个承诺(当解决时)将使结果可用。

其次,当你想调用一些在循环中返回一个 Promise 的异步操作并且你想知道在循环中启动的所有异步操作何时完成时,通常的技术是将 Promise 累积在一个数组中并使用Promise.all() 告诉你它们什么时候都完成了。

第三,您的超长变量名使您的代码极难阅读。我不知道您是否只是为了您的问题而这样做,或者您是否通常以这种方式编码,但我发现名称太长以至于它们模糊了代码的流程和阅读。我为有意义的变量名鼓掌,但这种方式已经破坏了代码的可读性,我无法想象必须输入所有这些只是为了处理代码。

因此,在使变量名称(对我而言)更具可读性并应用上述技术之后,以下是您的代码的简化版本:

function get_idMap(str, apiKey) {
    let promises = [];
    let idMap = {};
    let santizedString = database_queries.sanitize_string(str);
    if (santizedString) {
        santizedString.split(/\s+/).forEach(function(word) {
        // 2017-02-27 -- for the sake of performance, we skip over any string of 2 letters or less.
        // This means headquarters_country_code and headquarters_state_code need special handling.
        if (word.length > 2) {
            promises.push(database_queries.get_profileMap(word).then(function(profileMap) {
                if (profileMap) {
                    idMap = merge_objects(idMap, transformProfile(profileMap));
                }
            }));
        });
    } else {
        console.log("the string value was null when apiKey was : " + apiKey); 
    }
    return Promise.all(promises).then(function() {
        return idMap;
    });
}

而且,由于这会返回一个 Promise,你可以这样使用它:

get_idMap(someStr, yourKey).then(function(idMap) {
    // use the idMap here
}).catch(function(err) {
    // handle error here
});

【讨论】:

  • 为什么投反对票?这不教如何解决 OP 代码中的问题类型吗?如果您提供反对意见反馈,也许我可以改进答案。
  • 你的变量名可能不够长。
  • 说真的。为什么会有多次反对票?这个答案有什么问题?
  • 这些是长变量名吗?在 Java 中,这将被写为“Map> field_values = new Map>();”这是大约相同的长度。由于 Javascript 是动态的,我们使用名称来携带类型信息,尽管我们很幸运,我们不必经历 Java 要求我们完成的所有仪式。
  • @LRK9 - 有意义的变量名称很好。名字太长了,如果不使用复制/粘贴,您就无法遵循代码流程或记住要键入的内容,这显然太过分了。我猜这里的大多数人会说这些名字太长了,以至于他们模糊而不是帮助人们理解代码(这是我的观点)。此外,在这些名称中的许多名称中有很多多余的信息,这些信息对于理解函数的作用或工作原理是不必要的。而且,其中一些信息属于注释,而不是变量的每次使用。我的意见。
猜你喜欢
  • 2019-03-25
  • 2020-11-28
  • 2020-05-18
  • 2019-03-09
  • 1970-01-01
  • 2014-10-15
  • 1970-01-01
  • 2020-05-31
  • 2018-05-23
相关资源
最近更新 更多