返回 Then 为 Undefined。 NodeJS 中的 Q

Returning Then as Undefined. Q in NodeJS

我正在尝试 return 来自我的 REST 请求的值,并且在成功处理程序中我 return 将所有值作为延迟承诺但是当我 运行 landingPage 函数我无法解决延迟承诺。它给我 .thenundefined。我将 Unirest 库用于 HTTP 请求,将 Q 用于 Promises。

是否因为请求回调中的 return 在服务器可以获取数据之前 return 更早地编辑了数据,因此它没有 return 编辑了 deferred 对象或其他东西。

代码如下:

var landingPage = function (dir) {
    Uni.get('https://'+getDirectory(dir).url)
        .header('Content-Type','text/html')
        .end(function (lp_data) {
            var deferred = Q.defer();
            if (lp_data.raw_body) {
                var $ = cheerio.load(lp_data.raw_body),
                    cn_europe = $('#location_europe .list-countries li'),
                    cn_asia = $('#content-location_asia_pacific li'),
                    cn_north_america = $('#content-location_north_america li');

                // Get Europe Company List
                var europe = [];

                for (var i = 0; i < cn_europe.length; i++) {
                    var country_name = $(cn_europe[i]).find('a').html().split('(')[0].trim(),
                        esomar_url = 'https://' + getDirectory(dir).url + '/' + $(cn_europe[i]).find('a').attr('href');
                    europe.push({country_name: country_name, esomar_url: esomar_url});
                }

                return europe.length ? deferred.resolve(europe) : deferred.reject(err);
            }
        });
};

var tests = {
    t1: function (dir) {
        landingPage(dir)
            .then(function (r) {
                console.log(r);
            })
    }
}

您的主要功能 landingPage 没有 returning 值。它里面的代码产生了一个承诺,但你也应该 return 它。

因为你想 return deferred 持有的承诺,你应该使 deferred 成为定义在外部函数作用域,所以你可以 return 它定义的 promise (deferred.promise):

var landingPage = function (dir) {
    var deferred = Q.defer(); // *** define here
    Uni.get('https://'+getDirectory(dir).url)
        .header('Content-Type','text/html')
        .end(function (lp_data) {
            var europe = []; // *** define here, before the `if`
            if (lp_data.raw_body) {
                var $ = cheerio.load(lp_data.raw_body),
                    cn_europe = $('#location_europe .list-countries li'),
                    cn_asia = $('#content-location_asia_pacific li'),
                    cn_north_america = $('#content-location_north_america li');

                // Get Europe Company List
                for (var i = 0; i < cn_europe.length; i++) {
                    var country_name = $(cn_europe[i]).find('a').html().split('(')[0].trim(),
                        esomar_url = 'https://' + getDirectory(dir).url + '/' + $(cn_europe[i]).find('a').attr('href');
                    europe.push({country_name: country_name, esomar_url: esomar_url});
                }
            }
            // *** Move this out of the above `if`, so you always resolve/reject:
            return europe.length ? deferred.resolve(europe) : deferred.reject(err);
        });
    // *** return the promise (it will not be resolved yet, but that is the idea):
    return deferred.promise;
}

但是,在 Unirest 中有一个支持 promises 的请求(参见 here),它允许您这样做:

var landingPage = function (dir) {
    // return the promise that will now come from this chain:
    return Uni.get('https://'+getDirectory(dir).url)
        .header('Content-Type','text/html')
        .end()
        .exec() // turn request object to a promise
        .then(function (lp_data) {
            var europe = []; // *** define here, before the `if`
            if (lp_data.raw_body) {
                var $ = cheerio.load(lp_data.raw_body),
                    cn_europe = $('#location_europe .list-countries li'),
                    cn_asia = $('#content-location_asia_pacific li'),
                    cn_north_america = $('#content-location_north_america li');

                // Get Europe Company List
                for (var i = 0; i < cn_europe.length; i++) {
                    var country_name = $(cn_europe[i]).find('a').html().split('(')[0].trim(),
                        esomar_url = 'https://' + getDirectory(dir).url + '/' + $(cn_europe[i]).find('a').attr('href');
                    europe.push({country_name: country_name, esomar_url: esomar_url});
                }
            }
            // *** Return the data. Throw an error if to be rejected
            if (!europe.length) throw "no data!!";
            return europe;
        });
}

这样您就不必自己使用 deferred 对象转换为 promise。