2017-04-16 113 views
0

我對Node.js和Javascript很新,所以請原諒我對Bacchanalia的回調機制的困惑。在NodeJS中處理異步URL解析

我的問題

我建立一個簡單的Node.js應用程序,它接收HTTP請求併發送自己的JSON主體有效載荷與他們的URL的參數組合成一個輸入的功能。爲了學習,我不使用任何外部框架或npm包。

所以基本上,

curl -i \ 
    -H "Content-Type: application/json" \ 
    -X POST \ 
    -d '{"jsonKey":"jsonValue"}' \ 
    'http://localhost:8888/y?urlKey=urlValue' 

應該調用任意函數f與參數f({"jsonKey":"jsonValue", "urlKey":"urlValue"})

轉換的URL參數表是非常簡單,不需要任何回調都:

/* Parse the URL arguments */ 
function parseArguments(request) { 
    var url_obj = url.parse(request.url, true); 
    return url_obj.query; 
} 

當我嘗試了JSON有效載荷添加到返回的值情節複雜:

/* Parse the URL arguments and the JSON payload */ 
function parseArguments(request) { 
    // URL Parameters 
    var arguments_as_object = url.parse(request.url, true).query; 

    // JSON Payload, if any 
    var body = []; 
    request.on('data', function(chunk) { 
     body.push(chunk); 
    }).on('end', function() { 
     body = Buffer.concat(body).toString(); 
     if (body) { 
      body = JSON.parse(body); 
      Object.assign(arguments_as_object, body); 
     } 
     console.log(new Date(), "Arguments with JSON are ", arguments_as_object); 
    }); 

    console.log(new Date(), "Return value is ", arguments_as_object); 
    return arguments_as_object; 
} 

日誌是:

2017-04-16T13:14:47.807Z 'Return value is ' { a: 'b' } 
2017-04-16T13:14:47.826Z 'Arguments with JSON are ' { a: 'b', jsonKey: 'jsonValue' } 

不出所料,parseArguments返回之前由於JavaScript的異步性質,JSON解析完成。

我的問題

如何,我可以得到異步調用的結果,並使用它們的功能之外?除了發送回調函數及其所有參數之外,還有其他方法嗎?

有什麼我試圖

+0

你不能。異步操作在函數返回之前不會完成,因此無法從函數返回異步結果。你將不得不使用回調或承諾。看到[標記重複](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call)各種選擇。我建議從你的函數返回一個promise,然後調用者可以使用'.then()'來獲得異步結果。 – jfriend00

回答

1

我想你已經或多或少的回答了你自己的問題。您必須使用回調而不是返回值。

您可以在一定程度解決您在通過包裝該函數在另一個函數發送所有的回調參數parseArguments關注:

function mainFunc = (a, b, c, jsonData) { 
... 
}  
function parseCb = (jsonData) { 
mainFunc(1,2,3, jsonData) 
} 
parseArguments(request, parseCb) 

您也可以通過實現承諾注入清晰度的水平,你的異步代碼,它可以像同步變量一樣返回並傳遞:

function parseArguments(request) { 

return new Promise((resolve, reject) => { 
    // URL Parameters 
    var arguments_as_object = url.parse(request.url, true).query; 

    // JSON Payload, if any 
    var body = []; 
    request.on('data', function(chunk) { 
     body.push(chunk); 
    }).on('end', function() { 
     body = Buffer.concat(body).toString(); 
     if (body) { 
      body = JSON.parse(body); 
      Object.assign(arguments_as_object, body); 
      resolve(arguments_as_object) 
     } 
     console.log(new Date(), "Arguments with JSON are ", arguments_as_object); 
    }); 

    console.log(new Date(), "Return value is ", arguments_as_object); 
    return arguments_as_object; 
} 
})