如何从NodeJS中的循环返回Promise?

时间:2017-07-31 16:38:09

标签: node.js promise

我需要建立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;
    });
}

1 个答案:

答案 0 :(得分:1)

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

其次,无论何时你想调用一个在循环中返回promise的异步操作,你想知道循环中所有异步操作何时完成,通常的技术是在数组中累积promises并使用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;
    });
}

而且,既然这会返回一个承诺,你会像这样使用它:

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