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

我有两个js文件screenshot.js和main.js,我想从screenshot.js返回JSON到main.js,但是它没有返回结果,在你运行console.log的时候在screenshot.js文件中(this.result )你看到在控制台的结果,但是当你在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....' ); 

你的操作是asynchronous的。 完成之前无法获取结果。 在asynchronous操作完成之前,您正在调用.get()您需要从.run()返回一个promise,然后使用.then() ,而不是将结果存储在实例数据中,而无法告诉它何时准备。

作为一般规则,任何时候你在一个asynchronouscallback中获得一个结果,并且把它分配给一个更高级别的variables,这是一个重要的警告信号,你可能会做一些错误的事情,因为更高级的范围中的代码将没有当这个价值是有效的想法。 相反,您需要使用asynchronouscallback中的值,从该callback中调用某个函数,并将该值传递给函数,或者将值返回给承诺,以便调用者可以将其作为承诺的履行值这就是我改变你的代码在下面)。

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

 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() ,你可以像这样使用返回的promise:

 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....' ); 

我没有办法自己testing这个,但是这应该是run()方法的一个较less嵌套的版本。 这在可能的情况下使用链接,只有在.then()处理程序需要访问之前的结果时才嵌套。

 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}); }); } }); }); } } 

注意:我想你也错过error handling,如果有错误,调用page.close()

这里有一个对closePage()进行error handling的版本,所以无论我们如何离开这段代码,即使发生了错误,

 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; }); }): } }