Javascript 如何在NodeJS createServer中调用模块函数

Javascript 如何在NodeJS createServer中调用模块函数,javascript,node.js,Javascript,Node.js,我有两个js文件screenshot.js和main.js,我想将JSON从screenshot.js返回到main.js,但它没有返回结果,当你运行console.log(this.result)时,你会在console中看到结果,但当你在main.js文件中调用它时,结果是空的,如何解决这个问题 这是我的密码 screenshot.js module.exports={ result: '', run: function(url,w,h){ var phantom=require('phan

我有两个js文件screenshot.js和main.js,我想将JSON从screenshot.js返回到main.js,但它没有返回结果,当你运行console.log(this.result)时,你会在console中看到结果,但当你在main.js文件中调用它时,结果是空的,如何解决这个问题

这是我的密码

screenshot.js

module.exports={
result: '',
run: function(url,w,h){
var phantom=require('phantom');
phantom.create().then(function(ph){
    ph.createPage().then(function(page){
        page.property('viewportSize',{width:w,height:h}).then(function(){
            page.open('http://' + url + '/').then(function(status){
                page.property('onLoadFinished').then(function(){
                    console.log(status);
                    if (!(status == 'success')){
                         this.result={'image':'no'};
                         this.result=JSON.stringify(this.result);
                        //  console.log(this.result);
                            page.close();
                    } else {
                this.result=page.renderBase64('jpeg').then(function(img){
                                this.result={'image': img};
                                this.result = JSON.stringify(this.result);
                                //  console.log(this.result);
                                page.close();
                        });
                    }
                });
            });
        });
    });
});
return this;
},
get: function(){
return this.result;
}
}
main.js

var http = require( 'http' );
var parsing = require( 'url' );
var screenshot = require( './screenshot' );
http.createServer( function( req, res ) {
var url, img, w, h, query_object, result;
url = req.url;
url = url.replace( '/', '' );
url = url.trim();
if ( !( url == 'favicon.ico' ) ) {
  console.log( url );
  query_object = parsing.parse( req.url, true ).query;
  console.log( query_object );
  res.writeHeader( 200, { "Content-Type": "text/html" } );
  w = parseInt( query_object.width );
  h = parseInt( query_object.height );
  result = screenshot.run( url, w, h ).get();
  console.log( result );
  res.end();
}
}).listen( 80, '127.0.0.1' );

console.log( 'server isn running....' );

您的操作是异步的。在完成之前,您无法获取结果。在异步操作完成之前很久,您就调用了
.get()
。您需要从
返回一个承诺。运行()
并使用
。然后()
,不要将结果存储在实例数据中,而不知道它何时准备就绪

一般来说,任何时候,当您获取在异步回调中获得的结果并将其分配给某个范围更大的变量时,这都是一个主要的警告信号,表明您可能做错了什么,因为范围更大的代码不知道该值何时有效。相反,您需要在异步回调中使用该值,从该回调中调用某个函数并将该值传递给该函数,或者在承诺中返回该值,以便调用者可以将其作为承诺的已实现值使用(这就是我在下面更改代码的原因)

下面是一个重写版本,它返回一个承诺,并将结果作为承诺的履行值返回:

module.exports = {
    run: function (url, w, h) {
        var phantom = require('phantom');
        return phantom.create().then(function (ph) {
            ph.createPage().then(function (page) {
                page.property('viewportSize', {
                    width: w,
                    height: h
                }).then(function () {
                    page.open('http://' + url + '/').then(function (status) {
                        page.property('onLoadFinished').then(function () {
                            console.log(status);
                            if (status != 'success') {
                                page.close();
                                return JSON.stringify({'image': 'no'});
                            } else {
                                return page.renderBase64('jpeg').then(function (img) {
                                    page.close();
                                    return JSON.stringify({'image': img});
                                });
                            }
                        });
                    });
                });
            });
        });
    }
}
稍后,我也会发布一个更好的方法来写这篇文章,它不会使用太多的承诺嵌套

而不是调用
.get()
,只需使用返回的承诺,如下所示:

var http = require( 'http' );
var parsing = require( 'url' );
var screenshot = require( './screenshot' );
http.createServer( function( req, res ) {
    var url, img, w, h, query_object, result;
    url = req.url;
    url = url.replace( '/', '' );
    url = url.trim();
    if ( !( url == 'favicon.ico' ) ) {
      console.log( url );
      query_object = parsing.parse( req.url, true ).query;
      console.log( query_object );
      res.writeHeader( 200, { "Content-Type": "text/html" } );
      w = parseInt( query_object.width );
      h = parseInt( query_object.height );
      screenshot.run( url, w, h ).then(function(result) {
          console.log( result );
          res.end();
      });
    }
}).listen( 80, '127.0.0.1' );

console.log( 'server isn running....' );

我自己没有办法测试它,但这应该是
run()
方法的嵌套更少的版本。这在可能的情况下使用链接,仅在遵循
时使用嵌套。然后()
处理程序需要访问先前的结果

module.exports = {
    run: function (url, w, h) {
        var phantom = require('phantom');
        return phantom.create().then(function (ph) {
            return ph.createPage();
        }).then(function (page) {
            // nest other calls here so they all have access to the page argument
            return page.property('viewportSize', {width: w, height: h }).then(function () {
                return page.open('http://' + url + '/');
            }).then(function (status) {
                return page.property('onLoadFinished').then(function() {return status;});
            }).then(function (status) {
                console.log(status);
                if (status != 'success') {
                    page.close();
                    return JSON.stringify({'image': 'no'});
                } else {
                    return page.renderBase64('jpeg').then(function (img) {
                        page.close();
                        return JSON.stringify({'image': img});
                    });
                }
            });
        });
    }
}

注意:我认为您还缺少在发生错误时调用
page.close()
的错误处理

这是一个为
closePage()
添加了错误处理的版本,因此每当打开页面时,无论我们如何保留此代码,页面都将关闭,即使出现错误:

module.exports = {
    run: function (url, w, h) {
        var phantom = require('phantom');
        return phantom.create().then(function (ph) {
            return ph.createPage();
        }).then(function (page) {
            var pageOpen = false;

            function closePage(val) {
                if (pageOpen) {
                    page.close();
                }
                return val;
            }

            // nest other calls here so they all have access to the page argument
            return page.property('viewportSize', {width: w, height: h }).then(function () {
                return page.open('http://' + url + '/');
            }).then(function (status) {
                pageOpen = true;
                return page.property('onLoadFinished').then(function() {return status;});
            }).then(function (status) {
                console.log(status);
                if (status != 'success') {
                    return JSON.stringify({'image': 'no'});
                } else {
                    return page.renderBase64('jpeg').then(function (img) {
                        return JSON.stringify({'image': img});
                    });
                }
            }).then(function(closePage), function(err) {
                closePage();
                throw err;
            });
        }):
    }
}