简体   繁体   English

node.js表达,一种非常奇怪的行为

[英]node.js express, a very strange behaviour

I have an Express server running. 我有一台运行的Express服务器。

What i do is upload an Excel File from HTML and then Express parse that file and do some calculating. 我所做的是从HTML上传Excel文件,然后Express解析该文件并进行一些计算。

In the Excel file, each row has information about address of a User. 在Excel文件中,每行都包含有关用户地址的信息。

For each Address, our Express server will use google map geocoding API to calculate the latitude & longitude. 对于每个地址,我们的Express服务器将使用谷歌地图地理编码API来计算纬度和经度。

But, because Google doesn't accept more than 50 request per second to their geocoding API, so i have to use settimeout to delay the calculating. 但是,由于Google每秒对其地理编码API不接受超过50个请求,因此我必须使用settimeout来延迟计算。

For example if the Excel file has 50 addresses, so i have to use settimeout on each address to avoid that rate limit. 例如,如果Excel文件有50个地址,那么我必须在每个地址上使用settimeout以避免该速率限制。

Here is my code to use settimeout and calculate latitude, longitude 这是我使用settimeout并计算纬度,经度的代码

 createFromFile(req, res) { var form = new formidable.IncomingForm(); return form.parse(req, function (err, fields, files) { if (err) return res.status(500).json({error: err.message}) var workbook = new exceljs.Workbook(); return workbook.xlsx.readFile(files.excelfile.path).then(function() { // use workbook var worksheet = workbook.getWorksheet(1) var data = [] for (var i=2; i<=worksheet.rowCount; i++) { data.push({ from_name: worksheet.getCell('A'+i).value + '', from_address: worksheet.getCell('B'+i).value + '', from_phone: worksheet.getCell('C'+i).value + '', receiver_name: worksheet.getCell('D'+i).value + '', receiver_address: worksheet.getCell('E'+i).value + '', receiver_phone: worksheet.getCell('F'+i).value + '', note: worksheet.getCell('H'+i).value + '' }) } var delay = function(t) { return new Promise(function(resolve) { setTimeout(resolve, t) }) } return Promise.all(data.map(function(item, i) { return function() { return delay(750*i).then(function() { winston.log('debug', 'process for item '+i) return geocoder.geocode(item.from_address).then(function(geo_data) { data[i].from_coord = { lat: geo_data[0].latitude, lng: geo_data[0].longitude } return geocoder.geocode(item.receiver_address).then(function(geo_data) { data[i].receiver_coord = { lat: geo_data[0].latitude, lng: geo_data[0].longitude } }) }) .catch(function(geo_error) { winston.log('error', 'geo_error', {error: geo_error}) throw new Error('Address in line ' + i + ' is not valid') }) }) }() })) .then(function() { winston.log('debug', 'we are done calculating location') return res.status(201).json(data) }) }) .catch(function(e) { winston.log('error', 'an error occurred') return res.status(500).json({error: e.message}) }) }) } 

And below is my codes to call that Express API, i used React to do frontend job & used javascript fetch api to request to server. 下面是我调用Express API的代码,我使用React做前端工作并使用javascript fetch api来请求服务器。

 startUploadFile() { this.props.showLoader() let data = new FormData() data.append('excelfile', this.state.selectedFile) data.append('name', 'excelfile') var me = this fetch(Const.restServer + '/create-from-file', { headers: { 'Access-Token': this.props.access_token, }, method: 'POST', body: data }) .then(function(r) { return r.json() }) .then(function(r) { if (r.hasOwnProperty('error')) throw new Error(r.error) me.props.hideLoader() me.props.showDialog('success', 'Process Complete') }) .catch(function(e) { console.log(e) me.props.hideLoader() me.props.showDialog('error', e.message) }) } 

My problem is when i used above codes to uploading a file on browser, i see two request in express log file. 我的问题是,当我使用上面的代码在浏览器上上传文件时,我在快速日志文件中看到两个请求。 Something like this: 像这样的东西:

Express Server日志文件 I will provide my codes to log info of every request here too 我也会提供我的代码来记录每个请求的信息

 app.use(function(req, res, next) { winston.log('debug', 'call api:', { api: req.url, requestMethod: req.method }) res.header("Access-Control-Allow-Origin", "*"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Access-Token, Web-Admin-Request" ); next() }); function isAuthenticated(req, res, next) { /** ** Rest API Middleware check if access_token is valid */ let accessToken = req.body.accessToken || req.get('Access-Token') // bunch of codes to check accessToken next() } app.post('/order/create-from-file', isAuthenticated, orderController.createFromFile); 

I don't understand why this happen. 我不明白为什么会这样。 If I use Postman & select a File & upload, it works fine - just only One Request in logs. 如果我使用Postman并选择一个文件和上传,它工作正常 - 只有日志中的一个请求。

Can anyone tell me what is the reason. 谁能告诉我是什么原因。 I feel like this is a Bug of Express. 我觉得这是一个快递的Bug。 My Express version is 4.15.2 我的快递版本是4.15.2

The Access-Token request header your code adds to the request triggers browsers to send a CORS preflight OPTIONS request before trying the POST request. 您的代码添加到请求的Access-Token请求标头会在尝试POST请求之前触发浏览器发送CORS预检OPTIONS请求。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests gives more detail but the gist of it is, as long as your code's adding that Access-Token header to the request, there's no way you can prevent browsers from making the extra preflight OPTIONS request—because it's something browsers do automatically as part of the CORS protocol. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests提供了更多详细信息,但它的要点是,只要您的代码将Access-Token标头添加到请求中,就没有了你可以阻止浏览器进行额外的预检OPTIONS请求 - 因为它是浏览器自动作为CORS协议的一部分。

The reason you don't see the extra request when you use Postman is that it doesn't do the CORS preflight OPTIONS request—only browsers send it, and only for requests made by XHR/Fetch from frontend JavaScript code running in a browser at a specific origin (which Postman isn't). 当您使用Postman时没有看到额外请求的原因是它不执行CORS预检OPTIONS仅请求浏览器发送它,并且仅针对XHR / Fetch从浏览器中运行的前端JavaScript代码发出的请求特定的起源(邮差不是)。

Well, finally i can fix this problem by passing 'Access-Token' into request body instead of request header (now, my server always receive only one request). 好吧,最后我可以通过将'Access-Token'传递到请求体而不是请求头来解决这个问题(现在,我的服务器总是只收到一个请求)。 Thank to @sideshowbarker because your comment trigger me to do this method. 感谢@sideshowbarker,因为您的评论会触发我执行此方法。

I still think this Problem is a bug in Express, but because it didn't occur on my local development environment, so i will not send a report to them. 我仍然认为这个问题是Express中的一个错误,但因为它没有在我的本地开发环境中发生,所以我不会向他们发送报告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM