2016-10-31 107 views
0

我在項目中使用節點畫布;本質上該項目是關於在瀏覽器屏幕上顯示圖像,並能夠通過REST API POSTs控制圖像的位置。這工作正常,但在POST上我想自動刷新瀏覽器。Javascript節點js瀏覽器刷新POST

我已經看過:

  • NPM包(瀏覽器刷新等);但他們需要把一些代碼放在客戶端頁面,但我沒有任何HTML客戶端頁面。

  • 調用res.redirect;這似乎沒有做任何事情。

  • 在POST方法中調用我的draw()方法:我得到'write after end'的錯誤。

有幫助嗎?同樣,問題是刷新瀏覽器(或其中的一部分)在POST方法中的新座標上。

下面的代碼。

乾杯, 馬特

節點server.js:

//Lets require/import the HTTP module 
var http = require('http'); 
var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser') 
var fs = require('fs') 
var path = require('path') 

var draw = require('./draw_badge'); 

var robot1; 
var robot1_xcoord = 30;  
var robot1_ycoord = 100;  

var robot2; 
var robot2_xcoord = 50; 
var robot2_ycoord = 30;  

/** bodyParser.urlencoded(options) 
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST) 
* and exposes the resulting object (containing the keys and values) on req.body 
*/ 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 
/**bodyParser.json(options) 
* Parses the text as JSON and exposes the resulting object on req.body. 
*/ 
app.use(bodyParser.json()); 

/** -------- Start ----- 
* 
*/ 



    { 
    app.get('/', function (req, res) { 

    console.log("Xcoord: " + robot1_xcoord); 
    res.setHeader('Content-Type', 'image/png'); 
    // redraw everything 
    draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 

}); 


// Getting a POST 
app.post('/', function (req, res) { 
    console.log(req.body.id); 
if (req.body.id=="1") 
{ 
    console.log("robot1 change"); 
    robot1_xcoord = req.body.xcoordinate; 
    robot1_ycoord = req.body.ycoordinate; 
} 
else 
if (req.body.id=="2") 
{ 
    console.log("robot2 change"); 

    robot2_xcoord = req.body.xcoordinate; 
    robot2_ycoord = req.body.ycoordinate; 
} 
// draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 
//res.redirect('localhost:5000'); 
res.send('Got a POST request'); 

// try 
//res.redirect(req.get('referer')); 
/* 
return http.get({ 
     host: 'localhost', 
     path: '/' 
    }, function(response) { 
     // Continuously update stream with data 
     var body = ''; 
     response.on('data', function(d) { 
      body += d; 
     }); 
     response.on('end', function() { 

      // Data reception is done, do whatever with it! 
      var parsed = JSON.parse(body); 

     }); 
    }); 
*/ 

}); 
// Main app - Listen 
app.listen(process.env.PORT || 5000, function() { 
    console.log('Example app listening !'); 
}); 

draw_badge.js:

var Canvas = require('canvas') 
var fs = require('fs') 


function draw_badge(x,y) { 


    var x, y, i 

    ctx.clearRect(0, 0, 120, 120) 

    ctx.save() 

    ctx.translate(160, 160) 
    ctx.beginPath() 
    ctx.lineWidth = 14 
    ctx.strokeStyle = '#325FA2' 
    ctx.fillStyle = '#eeeeee' 

    ctx.arc(x, y, 42, 0, Math.PI * 2, true) 
    ctx.stroke() 
    ctx.fill() 


return canvas; 
} 


function draw_robot(x,y) { 

var Image = Canvas.Image 
var canvas = new Canvas(600, 600) 
var ctx = canvas.getContext('2d') 


var img = new Image() 
img.src = canvas.toBuffer() 
ctx.drawImage(img, 0, 0, 50, 50) 
ctx.drawImage(img, 50, 0, 50, 50) 
ctx.drawImage(img, 100, 0, 50, 50) 

img.src = fs.readFileSync('./kuka.png') 
ctx.drawImage(img, 100, 0, img.width , img.height) 

//img = new Image() 
img.src = fs.readFileSync('./robot.jpeg') 
ctx.drawImage(img, x, y, img.width/2, img.height/2) 
// new 


canvas.createPNGStream().pipe(fs.createWriteStream('./image-robot.png')) 
return canvas 

} 

function draw(x1,y1,x2,y2) 
{ 
    Image = Canvas.Image, 
     canvas = new Canvas(600, 600), 
     ctx = canvas.getContext('2d'); 
    canvas = draw_robot(x1,y1); 
    canvas = draw_badge(x2,y2); 
    return canvas; 
} 

module.exports = draw; 
+0

什麼觸發了POST?如果除了客戶端的圖片之外沒有其他東西,你不能擁有POST嗎?客戶是什麼?如果客戶端是網絡瀏覽器,則不能在沒有HTML和/或JS的情況下進行POST ... – jcaron

+0

對服務器的調用(即curl調用)會觸發POST,並具有關於在哪裏繪製圖像的座標信息。 node-canvas允許我從服務器端渲染圖片..(請參閱draw_badge.js ..) – MattLieber

回答

1

他們的方式你想不能工作

  • 已交付給瀏覽器無法動態刷新,僅僅是因爲它是一個圖像的圖像。一旦服務器已經交付並且客戶端加載他們的工作完成。
  • 嘗試寫入請求(可能是數百個請求中的一個)當然會導致「寫入結束後」,因爲請求的結尾是圖像首次加載到瀏覽器中的時間。
  • 快速res.redirect函數不能在事後調用(請求後),也可以立即重定向,這是你不需要的。

簡單的解決方案:通過HTTP標頭(正確)

app.get('/', function (req, res) { 
    console.log("Xcoord: " + robot1_xcoord); 
    res.setHeader('Content-Type', 'image/png'); 
    // refresh every second 
    res.setHeader('Refresh','1'); 
    // redraw everything 
    draw(robot1_xcoord,robot1_ycoord,robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 

}); 

真正的解決方案刷新:流媒體圖像

你可以提供一個實際的圖像流。這個想法是,您對圖片的請求永遠不會被關閉,並且當您通過REST-API更改圖片時,下一張圖片將被傳送。從理論上講,你的瀏覽器會顯示它所得到的最後一個完整的框架,從而在瀏覽器窗口中「更新」你的圖像。這將是這裏的real解決方案,但是在實施時浪費的時間可能會很昂貴。這會在代碼中進行一些重新安排。

警告:僅Firefox,Chrome的支持已被刪除,因爲我剛剛得知:/

server.js

//Lets require/import the HTTP module 
var http = require('http'); 
var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser') 
var fs = require('fs') 
var path = require('path') 

var draw = require('./draw_badge'); 

var robot1; 
var robot1_xcoord = 30; 
var robot1_ycoord = 100; 

var robot2; 
var robot2_xcoord = 50; 
var robot2_ycoord = 30; 

// An array to hold a list of active clients 
var clients = []; 

// draw an initial version of your buffer 
var imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE); 
// get the size in bytes as well, we'll need it 
var length = imageData.byteLength; 

/** bodyParser.urlencoded(options) 
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST) 
* and exposes the resulting object (containing the keys and values) on req.body 
*/ 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 
/**bodyParser.json(options) 
* Parses the text as JSON and exposes the resulting object on req.body. 
*/ 
app.use(bodyParser.json()); 

/** -------- Start ----- 
* 
*/ 

app.get('/', function(req, res) { 
    // prepare header so that the browser will wait for arbitray updates 
    res.writeHead(200, { 
    'Content-Type': 'multipart/x-mixed-replace; boundary=--NEW_IMAGE_HERE', 
    'Cache-Control': 'no-cache', 
    'Connection': 'close', 
    'Pragma': 'no-cache' 
    }); 
    var on_update = function(imageData, length) { 
     try { 
     console.log("Updating client.. bytes:", length) 
     res.write("--NEW_IMAGE_HERE\r\n"); 
     res.write("Content-Type: image/png\r\n"); 
     res.write("Content-Length: " + length + "\r\n\r\n"); 
     res.write(imageData); 
     } catch (e) { // in case of an error remove from the clients array 
     console.log("Error: ", e); 
     clients.splice(clients.indexOf(on_update), 1); 
     } 
    } 
    // remove on disconnect 
    res.on('close', function() { 
    console.log("Disconnected"); 
    clients.splice(clients.indexOf(on_update), 1); 
    }); 
    // send the client our last cached version of the image 
    on_update(imageData, length); 
    // add our update function to the array of clients 
    clients.push(on_update); 
}); 

// Getting a POST 
app.post('/', function(req, res) { 
    console.log(req.body.id); 
    if (req.body.id == "1") { 
    console.log("robot1 change"); 
    robot1_xcoord = req.body.xcoordinate; 
    robot1_ycoord = req.body.ycoordinate; 
    } else 
    if (req.body.id == "2") { 
    console.log("robot2 change"); 
    robot2_xcoord = req.body.xcoordinate; 
    robot2_ycoord = req.body.ycoordinate; 
    } 
    res.send('Got a POST request'); 
    // redraw everything into the buffer 
    imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE); 
    length = imageData.byteLength; 
    // notify active clients 
    for (on_update of clients) { 
    on_update(imageData, length); 
    } 
}); 
// Main app - Listen 
app.listen(process.env.PORT || 5000, function() { 
    console.log('Example app listening !'); 
});