2015-09-24 48 views
1

我使用Express並試圖教自己node/javascript回調,我偶然發現了一些東西。如何從節點中的函數返回數據?

我有一個看起來像這樣的路線:

var express = require('express'); 
var router = express.Router(); 
var api = require('../api'); 

router.get('/',function(req, res, next){ 
    var modulename = api.modulename; 
    modulename.methodname(res); 
}); 

module.exports = router; 

然後就是被稱爲以上的模塊如下所示:

var library = require('library'); 
var instances = {}; 
var modulename = { 

    getAllInstances: function(res) { 
    var request = new library.asyncMethod(); 
    request.on('success', function(resp) { 
     instances = resp.data; 
     res.setHeader("Content-Type","application/json"); 
     var returnInstances = { 
     id: instances[0].InstanceId, 
     state: {name: instances[0].State.Name, code: instances[0].State.Code} 
     }; 
     res.send(returnInstances); 
    }) 
    .on('error', function(resp){ 
     console.log(resp); 
    }) 
    } 
}; 

module.exports = modulename; 

正如你可以看到我通過響應參數通過我的模塊,但我寧願傳回instances,然後在路線返回api.modulename.instances,如下所示:

var library = require('library'); 
var instances = {}; 
var modulename = { 

    getAllInstances: function() { 
    var request = new library.asyncMethod(); 
    request.on('success', function(resp) { 
     var returnData = resp.data; 
     instances = { 
     id: returnData[0].InstanceId, 
     state: {name: returnData[0].State.Name, code: returnData[0].State.Code} 
     }; 
    }) 
    .on('error', function(resp){ 
     console.log(resp); 
    }) 
    .send(); 
    } 
}; 

module.exports = modulename; 

但是,當我這樣做的時候,它會作爲默認值{}而出現,但如果我像上面那樣運行它,我確實會得到輸出,所以我知道應該有數據在那裏。

回答

1

讓我知道我是否誤解了你的問題。如果你說你要傳回從getAllInstances對象,那麼你在回調中傳遞,並從像這個 -

router.get('/',function(req, res, next){ 
    var modulename = api.modulename; 
    modulename.getAllInstances(res, function(err, instances){ 
    if(err){ ... } 
    else{ 
     res.send(instances); //or however you want to use instances 
    } 
    }); 
}); 

事件處理程序,並在getInstances

var modulename = { 
    getAllInstances: function(res, cb) { 
    var request = new library.asyncMethod(); 
    request.on('success', function(resp) { 
     instances = resp.data; 

     var returnInstances = { 
     id: instances[0].InstanceId, 
     state: {name: instances[0].State.Name, code: instances[0].State.Code} 
     }; 
     cb(null, instances); 
    }) 
    .on('error', function(err){ 
     cb(err, null)); 
    }); 
    //.send(); not sure what this is it seems to be request.send() ?? 
    } 
}; 
+0

cb(回調函數)將在哪裏聲明? –

+0

在javascript中正常使用異步編程是將其聲明爲匿名函數。在上面的例子中,它聲明瞭它的用處'modulename.getAllInstances(res,function(err,instances){'(我會發表評論)。這是一個非常常見的用法,特別是在節點。你可以在許多地方使用相同的回調函數,你可以聲明一個普通的函數,只需將函數名稱作爲cb參數傳入即可。無論哪種方式都可以。 –

+0

查看本文以獲取快速示例https://en.wikibooks.org/ wiki/JavaScript/Anonymous_Functions會查看它所說的位「匿名函數的最常見用法是作爲其他函數的參數」 –

0

這裏的問題在於把它當來自API調用的響應可用時。節點中的事件循環意味着代碼在API回覆響應之前不會阻塞。因此需要回調來處理該響應。您可能希望在Express路由器響應中使用API​​響應,因此存在一系列依賴關係。

這裏的一個策略是使用promises而不是回調,它會減輕您在使用API​​調用異步響應時遇到的一些痛苦。

在你的路線:

router.get('/',function(req, res, next){ 
    var instances = []; 
    // The function below could be refactored into a library to minimise controller code. 
    var resolver = function (response) { 
    var data = JSON.parse(response); 
    instances.push({ 
     name: data[0].State.Name, 
     code: data[0].State.Code 
    }); 
    res.render('instances'. {instances : instances}); 
    }; 

    modulename.methodname(resolver); 
}); 

而且你的模塊中:

var rp = require('request-promise'); // Also see q-io/http as an alternate lib. 

var modulename = { 
    methodname: function (resolver) { 
    rp('http://the-inter.net') 
     .then(resolver) 
     .catch(console.error); 
    } 
}; 

這可能不切正粘貼工作,但有一個看看request-promise examples進一步澄清。