2013-10-29 37 views
2

如何運行nodejs/expressjs中的多個函數?在php中,它很簡單,一個接一個地調用一個函數,但是這個節點中的回調業務令人困惑,我不斷收到一個變量未定義的錯誤等等。這是我在做什麼的基本想法。在nodejs/expressjs中運行多個函數

var express = require('express'); 
var request = require('request'); 

var app = express(); 

app.get('/user/:id', function(req, res) { 
    var id = req.params.id; 

    getInformation(id, function(info) { 
     res.send(info); 
    }); 
}); 

app.listen(3000); 

getInformation(id, callback) { 
    var qty = makeExternalApiCall(); 
    var color = secondFunction(id); 
    callback({quantity: qty, color: color}); 
} 

makeExternalApiCall() { 
    request({uri: 'https://provider.com/api/stuff/'}, function(error, response, body) { 
     if (!error && response.statusCode == 200) { 
     return body.qty; 
     } 
    } 
} 

secondFunction(id) { 
    //look up color by id 
    var color = "blue"; 
    return color; 
} 
+0

http://www.sebastianseilund .com/nodejs-async-in-practice – bryanmac

+0

研究javascript承諾 - 在youtube上有一些關於它的好的研討會 – megawac

回答

4

通過多個函數運行類似於它在PHP中,除非它涉及異步函數。異步回調函數可以在任何時候調用,並且不適用於return關鍵字。就拿這個回調例如:

var cb = function(arg) { 
    console.log(arg); 
}; 

我們可以通過這個回調函數到另一個函數,並具有該函數調用cb()從內:

function call(text, callback) { 
    callback(text); 
}; 

var txt = 'a string'; 
call(txt, cb); 
console.log('breakpoint'); 

上面的示例運行同步。因此,執行的順序是:

call() -> cb() 
console.log() 

但是,如果我們推遲函數或添加一個計時器(process.nextTick等待,直到函數的調用堆棧是空的,然後進行什麼活動已排隊):

function call(text, callback) { 
    process.nextTick(function() { 
    callback(text); 
    }); 
}; 

並再次運行它,我們得到了一個不同的執行順序,因爲cb()排隊運行後調用堆棧是空的(右後console.log()運行時,它是空的):

call() 
console.log() 
-> cb() 

大多數未定義的變量錯誤是由設置前訪問變量引起的。例如,採取異步功能foo()

var data; 

foo(function(bar) { 
    data = bar; 
}); 
console.log(data); 

回調function(bar) { ... });可以在console.log()之後被調用,這意味着console.log()運行data被賦予一個值之前。


至於你的具體問題,請求模塊是異步的,並使用回調,所以你不能使用HTTP請求中的返回值。要從回調函數中獲取結果值,您需要將其傳遞給另一個回調函數。使用return關鍵字將會停止函數的執行。因此,改變這種:

var options = { 
    uri: 'https://provider.com/api/stuff/' 
}; 

function makeExternalApiCall() { 
    request(options, function(err, res, body) { 
    if (!err && res.statusCode == 200) { 
     return body.qty; 
    } 
    } 
}; 

使用回調:

function makeExternalApiCall(callback) { 
    request(options, function(err, res, body) { 
    if (!err && res.statusCode == 200) { 
     callback(null, body.qty); 
    } 
    } 
}; 

的功能將被用於像這樣:

makeExternalApiCall(function(err, qty) { 
    // here is qty 
}); 

所以你的路由代碼可能是這樣的,使用嵌套回調:

function getInformation(id, callback) { 
    var color = secondFunction(id); 
    makeExternalApiCall(function(err, qty) { 
    callback({ quantity: qty, color: color }); 
    }); 
}; 

app.get('/user/:id', function(req, res) { 
    var id = req.params.id; 

    getInformation(id, function(info) { 
     res.send(info); 
    }); 
});