在主入口点使用带有promises的导入异步方法

时间:2017-10-18 15:04:23

标签: javascript node.js promise

我正在使用异步方法创建Node.js模块 - 一个简单的HTTP GET请求。这是代码:

//mymodule.js
var https = require('https');

function getSomething(url_str)
{
    var callback_fn = function(response){
        var body = '';

        response.on('data', function (data) {
            body += data;
        });

        response.on('end', function () {
            //console.log(body);
            return body;
        });
    };

    return https.request(url_str, callback_fn).end();
}

var module_obj = {
    getSome: getSomething
};

module.exports = module_obj;

这个模块由我的app.js调用 - 一个Web服务器 - 就像这样:

//app.js
var myModule = require('./mymodule');
var http = require('http');
var qs = require('querystring');

var server_fn = function(request, response){
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Request-Method', '*');
    response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
    response.setHeader('Access-Control-Allow-Headers', '*');
    if ( request.method === 'OPTIONS' ) {
        response.writeHead(200);
        response.end();
        return;
    }

    if (request.method == 'POST') {
        var body = '';

        request.on('data', function (data) {
            body += data;

            // Too much POST data, kill the connection!
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6)
                request.connection.destroy();
        });

        request.on('end', function () {
            var post = qs.parse(body),
                post_url = post.url,
                post_method = post.method;

            var promise_flow = new Promise(function(resolve, reject){
                if(post_method === 'get_me_something')
                {
                    response_str = myModule.getSome(post_url);
                    resolve(response_str);
                }
                else
                {
                    resolve('nothing');
                }
            });

            promise_flow
                .then(function(response){
                response.write(response);
                response.end();
                return;
            }).catch(function(error){
                response.write(error);
                response.end();
                return;
            })

        });
    }
};
var http_server = http.createServer(server_fn);
http_server.listen(2270);
console.log("server listening on 2270");

所以基本上,我通过node app.js启动,然后发布URL,然后模块应该获取网页,然后返回内容。

不幸的是,我收到了以下错误:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: First argument must be a string or Buffer

我认为这是因为我从模块getSomething方法获得的响应是​​false,而不是请求网页的内容。

我知道我可以通过从https.get移动mymodule.js操作并将其与app.js内联,然后在结束时调用resolve来解决此问题,但我&#39 ; d想保持当前的模块设置。

是否有一种解决方法可以让导入模块中的异步方法与现有的承诺链一起作为设置使用?

更新

经过进一步审查后,我注意到我并没有以正确的方式运行。我更新了代码如下:

//...
var promise_flow = new Promise(function(resolve, reject){
    if(post_method === 'get_me_something')
    {
        myModule.getSome(post_url)
            .then(function(data){
                resolve(data);
            })
            .catch(function(err){
                reject(err);
            });
    }
    else
    {
        resolve('nothing');
    }
});
//...

这样,我认为它符合Promise的真正精神。

1 个答案:

答案 0 :(得分:1)

您的getSomething函数未返回承诺。让它返回一个承诺,履行response.on('end')中的承诺。

function getSomething(url_str)
{
    return new Promise(function(resolve, reject) {
        var callback_fn = function(response){
            var body = '';

            response.on('data', function (data) {
                body += data;
            });

            response.on('end', function () {
                //console.log(body);
                resolve(body);
            });
        };
        https.request(url_str, callback_fn).end();
    });
}

然后在您的主文件中,将其称为:myModule.getSomething(post_url).then(resolve);