简体   繁体   中英

Nodejs module function returns undefined, not asynchronous

Pretty (very) new to Node so this is probably stupid. I have a module that defines various routes that I iterate over to define the app's routes. This works fine.

While setting up the route I want to call a function checkAvailableTranslation in another module language that checks whether a translation of that page exists in another language ( req.locale being the user's favoured language that we are trying to find a match for), and if so return a URL fragment for it.

The strings object is loaded from a json file and contains an item translations that is an array of ISO country codes mapped to URL fragments.

** app.js **

var routes = require("./config/routing.js")
routes.forEach(function(item) {
    item.routes.forEach(function(route) {
        app.get(route.path, function(req, res) {
            var strings = require(route.strings)
            translations = language.checkAvailableTranslation(req.locale, strings.translations))
            console.log(translations) // undefined?!?!?!?!
            res.render(route.render, {
                layout: route.layout,
                strings: strings
            })
        })
    })
})

** strings.translations **

[
    { "fr": "/fr" },
    { "ar": "/ar" },
    { "es": "/es" },
    { "pt": "/pt" },
    { "de": "/de" }
]

** language.js **

module.exports = function() {
    var module = {}

    module.checkAvailableTranslation = function(language, translations) {
        translations.forEach(function(el) {
            if( el[language] ) {
                console.log(el[language]) // this logs a matched language
                return el[language] // this disappears into the ether
            }
        })
    }
    return module
}

So everything generally behaves as expected with translations.forEach iterating successfully and finding matches. However it doesn't seem to return the value back to app.js - when I output the function's return I get undefined .

Does the fact that strings is being loaded from a json file make this an asynchronous call, as if it were a database? If so (and that would need explaining), what should I be doing here to set up a promise to deal with this?

You're returning from the forEach callback which is not possible. You need to iterate manually over the array or write the result into a variable in the scope of your checkAvailableTranslation method(but still iterate over all items in translations ).

Manual "forEach"

module.checkAvailableTranslation = function(language, translations) {
    for (
        var i = 0, translation = translations[i][language];
        i < translations.length;
        i++, translation = translations[i][language]
    ) {
        if (translation)
            return translation;
    }
}

Or using Array.prototype.some

function (language, translations) {
    var res;
    translations.some(function (translation) {
        return !!(res = translation[language]);
    });
    return res;
}

EDIT: Ninja approach :

function n(l,t,i){return t[i|0][l]||g(l,t,(i|0)+1)}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM