我读到关于Yaws的文章:将数据流式传输到客户端。我创建了一个如下所示的简单示例,但它不起作用。我犯了一个错误,这个过程正在消亡。
这是我的偏航文件:
<erl>
out(A) ->
Self = self(),
spawn(fun() ->
yaws_api:stream_chunk_deliver_blocking(Self, "Hello"),
yaws_api:stream_chunk_end(Self, "Thanks"),
exit(normal)
end),
{streamcontent, "text/html; charset=utf-8", "Firstrn"}.
</erl>
我也尝试过使用yaws_api:stream_chunk_deliver/2
,但是我得到了相同的错误。这是我在命令提示符中得到的错误消息:
=ERROR REPORT==== 13-Feb-2012::09:23:30 ===
Error in process <0.117.0> with exit value: {undef,[{yaws_api,stream_chunk_end,[
n"],[]}]}"Thanks
1>
=ERROR REPORT==== 13-Feb-2012::09:24:00 ===
Yaws process died: {stream_timeout,
[{yaws_server,stream_loop_send,5,
[{file,"yaws_server.erl"},{line,2821}]},
{yaws_server,aloop,3,
[{file,"yaws_server.erl"},{line,1167}]},
{yaws_server,acceptor0,2,
[{file,"yaws_server.erl"},{line,1025}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}
1>
最后一块似乎没有发送到客户端:
HTTP/1.1 200 OK
Server: Yaws 1.92
Date: Mon, 13 Feb 2012 07:31:18 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
7
First
7
Hello
以下是我使用的JavaScript客户端代码(仅适用于IE8和IE9),使用XDomainRequest:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script>
window.onload = function() {
var el = document.getElementById("requestbutton");
if(el.attachEvent) {
el.attachEvent('onclick', doXDR);
}
}
function writeStatus(message) {
var html = document.createElement("div");
html.setAttribute("class", "message");
html.innerHTML = message;
document.getElementById("status").appendChild(html);
}
function doXDR() {
if(!window.XDomainRequest) {
writeStatus("No XDR support in your browser");
return;
}
writeStatus("Beginning XDR");
try {
var xdr = new XDomainRequest();
xdr.open("GET", "http://localhost:8090/stream.yaws");
xdr.send();
xdr.onload = function() {
writeStatus("XDR response: " + xdr.responseText);
};
xdr.onerror = function() {
writeStatus("XDR error");
};
xdr.onprogress = function() {
writeStatus("XDR intermediate: " + xdr.responseText);
};
} catch (e) {
writeStatus("XDR Exception: " + e);
}
}
</script>
</head>
<body>
<h1>Test page</h1>
<button id="requestbutton">Send request</button><br>
<div id="status"></div>
</body>
</html>
在JavaScript客户端上,会调用xdr.onerror = function()
方法。客户端不应该在这个例子中显示任何数据,因为它需要2k前奏,但它应该被发送,正如我所理解的那样。
更新
在修复了Steve Vinoski指出的Erlang问题并删除了我的数据上的rn
之后,Yaws服务器发送了正确的数据。但我仍然在JavaScript客户端上收到xdr.onerror = function()
错误。我似乎需要向响应Access-Control-Allow-Origin: *
添加另一个标头,如XDomainRequest Object:中所述
该文档将通过发送一个包含Origin值的Origin标头来请求域服务器的数据。只有当服务器以*或请求文档的确切URL的Access Control Allow Origin标头进行响应时,它才会完成连接。此行为是万维网联盟(W3C)的Web应用程序工作组关于客户端跨域通信的框架草案的一部分,XDomainRequest对象与该框架集成。
如何将此标头添加到HTTP响应中?看起来我只能在返回值中设置MIME类型:{streamcontent, MimeType, FirstChunk}
?
任何时候,只要您看到undef
错误,就像上面显示的这个:
Error in process <0.117.0> with exit value: {undef,[{yaws_api,stream_chunk_end,
这意味着您正在调用不在加载路径上的模块中的函数,或者您正在调用一个不存在的函数。在您的代码中,您调用的是不存在的yaws_api:stream_chunK_end/2
。您想要的是yaws_api:stream_chunk_end/1
。将您的代码更改为以下内容:
<erl>
out(A) ->
Self = self(),
spawn(fun() ->
yaws_api:stream_chunk_deliver_blocking(Self, "Hellorn"),
yaws_api:stream_chunk_deliver_blocking(Self, "Thanksrn"),
yaws_api:stream_chunk_end(Self),
exit(normal)
end),
{streamcontent, "text/html; charset=utf-8", "Firstrn"}.
</erl>
然后我认为你的例子会很好用。
更新:
为了回答问题的新部分,您使用列表返回值,而不仅仅是一个元组,确保streamcontent
元组在列表中的最后一个:
[{header, {"Access-Control-Allow-Origin", "*"}},
{streamcontent, "text/html; charset=utf-8", "First"}].