分类: Javascript

Node.js socket stream 和异步函数

考虑如下实现场景:
使用 Node.js 实现一个服务端,客户端使用 Socket 连接之后处理数据并返回。
其中,处理数据的场景中很容易出现异步函数(比如数据库查询,或者读配置文件),导致还没把 chunk 处理完,pipe就跑到下一步去了,导致客户端直接被关掉了。
查了一晚上 so 和各种官方 github ,最后还是通过读官方文档解决了。
先给出解决方案。
在 Create Server 的时候,设置 allowHalfOpen 为 true 。
官方对这一参数的解释是:
allowHalfOpen Indicates whether half-opened TCP connections are allowed. See net.createServer() and the 'end' event for details. Defaults to false.
就是允许创建的 Socket 处于半开模式(数据流暂时停止而连接仍然建立)。这样的话,就可以让处理器 (parser) 放心地去处理数据,等返回后再将处理过的 chunk 吐回到 pipe 中。
不过有一点需要注意,如果允许了 HalfOpen ,那么就一定要在处理完数据后手动关掉 Socket ,也就是文中所说的调用 Socket.end() 方法,否则的话 tcp 连接就无法正常结束了。

exp.
简单实现场景:


const server = net.createServer({allowHalfOpen :true}, (socket) => {
    socket.once('error', (err) => {
        console.log('[ERROR]');
    });

    socket
        .pipe(...)
        .pipe(through2(function(chunk,enc,callback){
            let _this = this;
            _parser.parseData(chunk).then(function(chunk){
                _this.push(chunk);
                socket.end();
            }).catch(function(err){
                _this.push(err);
                socket.end();
            });
        }))
        .pipe(...)
    .pipe(socket);
});
server.listen(..., ..., () => {
    console.log('[INFO]');
});

其中,parseData是一个使用了 asnyc 方法的函数。

初识 react-intl

5.9更新
继续踩坑。
因为要传递自定义的函数,于是将 react-router 属性中的 component 改成了 render 。结果发现props中的 match 和 history 直接不见了。原因是又踩了另外一个坑。

正确的打开姿势是:

<Match exactly pattern="/" render={(props) => <Home msg={"hello"} {...props} />} />

*还是没有超过初学者的范畴,参考 git issue : https://github.com/ReactTraining/react-router/issues/4293
=============

最近拿手头一个小项目尝试了一下 React 。项目中涉及到了国际化(其实就是中英文切换),于是(也没有第二选择地)使用了雅虎出的 react-intl
说句实在话就是文档看的有点头疼,因为 react 自带全家桶属性,而它提供的挺多东西还是没能用得上的。
开发过程中参考了两个项目:
1)https://github.com/DWboutin/react-webpack-startup
2)https://segmentfault.com/a/1190000005824920
遇到的最大的问题就是在于要提供一个切换语言的按钮。 React 的组件化让我包在最外面的整站 IntlProvider 需要一层一层地把事件传递到页面内部。
大概结构就是:


<IntlProvider ...config>
<App>
...
<Router render={()=><PageContent changeLanguageFunc={this.changeLang}/>}>
...
</App>
</IntlProvider>

然后在<PageContent/>中通过 this.props.changeLanguageFunc 来调用。如果你的这个函数还在下一级的组件里,那就要继续传递了。
这个方法主要参考的是 AlloyTeam 的这篇文章:http://www.alloyteam.com/2016/01/some-methods-of-reactjs-communication-between-components/

真正学会 React 是个漫长的过程啊~

这个假红包

早上家族群里开始群发一个假的微信红包。我不禁有点好奇,微信这么强大的智能识别还是不能解决这个问题?于是起床抓了个包。
分享的地址是
shizhuang.ifeng.com/share/topic/159053-1-0?sz_ch=friend&sz_platform=2&skt=89341487982719
查看之后发现存在 xss 。

跟进去发现跳转到了
http://m.ufoto.com.cn/post/2523312?skt=83851487983287
这个页面槽点就更多了,当初写这个页面的程序员估计坟头草都几丈高了。基本没有标签过滤,就算做了有限的处理也是可以轻松绕过的。

看了一下 JS ,有点像当年挂马玩的那一套,关键字编码后直接在页面加载完成后替换整个全屏。其实微信要屏蔽这个也不是不可能,只要禁止掉内置浏览器中的通过 document.write 或者 js dom 操作注入的 html 代码段的跨域请求就可以了。
唉,难怪微信浏览器要设白名单。

从微信小程序导航学到的姿势

知晓程序
最早的一个微信小程序导航,但是大家都知道,微信么,立牌坊(并没有),并不支持直接识别二维码进入小程序。于是各类导航就不能直接把二维码打印在屏幕上让程序识别。于是各位导航都是各显神通。
之前闲逛发现这家解决了一个历史难题: Safari 操作剪贴板。
Clipboard
周末做了点 maimai 相关的微小的工作,于是就把这个工作交给了还要解 ticket 的花花( @liuyanghejerry )。
花花果然很快,五分钟就搞定了。
那么先 Show the code 。

var funs = {
  copySelectedRange: function(element) {
    var range = document.createRange();
    range.selectNodeContents(element);
    var selection = document.getSelection();
    selection.removeAllRanges(),
    selection.addRange(range),
    document.execCommand("copy", true);
  },
};

之后,发挥了单身程序狗的优秀特质,去 Can I use 上看了一眼。
发现上面竟然说的是
Only supports OS clipboard reading/writing via shortcut keys, not through document.execCommand().

这脸打的。

多看官网多读书

是的,依旧沉迷阴阳师。因此没有好好写文章。周末找个时间干了吧。
最近还在做一个官网,反正事儿也不是没有。
webpack 的 html-loader 是可以直接代替 apache/nginx 进行 server-side-include 的,虽然从原理上看似乎不是一个事儿。

https://github.com/webpack/html-loader

配置webpack的配置文件中,关于html的加载项:

{test: /\.html$/, loader: 'html?interpolate'},

即可。

===更新===

早上话说了一半。
完成上面的工作之后,在页面里面即可使用

${require('./tmpl/footer.tmpl.html')}

这样的语法来引用html模板了。这个 require 可以使用已有的 loader 来载入各种神奇的东西,比如 css js等等,来做各种黑科技。