免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345
最近访问板块 发新帖
楼主: send_linux
打印 上一主题 下一主题

[JavaScript] Web开发技术讨论之二:如何编写高效JavaScript代码 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
41 [报告]
发表于 2014-03-24 01:28 |只看该作者
starwing83 发表于 2014-03-23 21:11
然后说说你提到的什么数据冗余性的事儿——我才不管呢,能工作就成,管你optional不optional,反正现在大部分的域都是optional,也没觉得有多不好,反正硬盘便宜。

比如。。。 用户有联系邮箱、头像图片链接、性别、生日等等,它们都是可选填的。
你的意思是说,它们都在一个表里,没填的NULL就行了? 那估计是会被SQL evangelist批评的

前面说的EAV:

  1. id user_id attribute value
  2. 1  1       contact   CU@gmail.com
  3. 2  1       avatar    http://cu.img168.net/static/image/common//folder_new.gif
  4. ...
复制代码
也是时不时就被选出来作为反面例子示众。。。

user_contact, user_avatar, user_gender, user_birthday 分别一张表才是正统,其他都是邪门歪道!!!

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
42 [报告]
发表于 2014-03-24 02:16 |只看该作者
回复 39# OwnWaterloo


    虽然大家都说mapping,但是很显然mapping是不可能的——SQL的操作对象是集合,ORM都映射到独立Object了,怎么个集合法儿?

要直接操纵集合,现代的ORM应该还不可能——sequelize有BlukCreate,支持集合创建,还有集合删除,至于集合修改嘛= =

所以,M当作Model其实更简单——就是独立进行的操作,如果你要对一堆东西进行操作,烦请SQL(或者上面提到了的,SQL的某种DSL方言= =)

反正总的来说,你觉得纠结还不是因为SQL功能太强了么= =你要是用不到那些超级功能那关那些干嘛= =反正我现在基本上只是处理单个用户请求——服务器嘛——至于多个用户要怎么怎么样,我目前能想到的唯一办法就是自己写脚本——是SQL脚本还是SQL-DSL脚本有区别么= =

恩,所以你说对了,的确就是只解决80%问题的——我说的完备性是在操作单个元素与其对应关系上,集合和集合的关系嘛,这个有时间可以做做理论研究的说~

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
43 [报告]
发表于 2014-03-24 02:19 |只看该作者
回复 41# OwnWaterloo


    对,就是没有就是NULL

批评就批评,管我鸟事,又不是客户,又没给钱,随便批评。哪天要是捐我一台服务器什么的我再去改改……

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
44 [报告]
发表于 2014-03-24 02:28 |只看该作者
bluebird不是提到了Q么= =别的好像还有,不记得了,我就是在README.md看到的,其他的不知道诶。 。

反正说是比Q好,而我之前用着Q,再然后我的ORM用的它,我不用它用啥= =

我想想上面还有啥问题= =哦,Promise标准是吧?这个是有的,Promise/A+(我不知道是不是啊,但是Q和bluebird都这么说,感觉是标准吧?)反正都实现了这个接口了。其他的扩展什么的多得要命,没用到的就不看,我现在很没节操的。

并行那个,map是等待所有完成然后返回,没有超时,只要有一个失败就全部失败,而且没有rollback,不管那么多了,够用就成= =

Q貌似还有其他的各种选项,比如any(所有操作完成返回,不管失败,没有超时),感觉做超时应该也成,就是没人做罢了

反正还是那句话,也没打算研究,有什么用什么,一切以节约代码为第一优先级,以后出问题——那不是还有以后嘛= =

token就是用户标记,类似cookie的东西,但是不存信息,就是代表你是谁的。至于操作的状态都存数据库了,数据库说可以就可以= =反正REST是没状态的就是了= =客户端这边也维护一套状态,免得知道不行还发请求,大体就是这样了,不知道这算不算REST,反正这玩意儿听起来挺玄乎的,唯一靠谱的就是我说的那两点:
1. 所有资源都有地址
2. 所有资源都最多支持四种操作

如果算上错误也算是操作,那么就是所有资源都支持四种操作(最多出错嘛)

那么按照你说的,我是不是可以这么理解S,所谓状态就是:资源的表示能提供访问更多操作的可能性?

也就是说,我不知道有多少用户,我GET /user,得到一个列表,这样我就能对我获取的用户进行操作了——因此状态(就有机会)改变了?不然我就只知道这一个接口,谈不上能改变状态。

这么说,S其实说的不是状态,而是【获取可以进行其他操作的必要信息】,是这个理解么

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
45 [报告]
发表于 2014-03-24 02:37 |只看该作者
starwing83 发表于 2014-03-23 21:11
我前段时间找了很多REST的文章看看——主要目的是看看这货是不是又是一个卖名词的,后来发现还是有点儿货的。什么状态转换都是装逼的,其实就是很简单的一件事儿:
1. 所有东西都有地址
2. 所有东西都支持共同的操作


前面把这看掉了。 状态转换其实是REST(in Roy Fielding's mind)的要点之一。
有一个给REST评级的网站。 链接忘了。。。  具体的评级顺序也忘了。。。
单一的end point(/index.php, /api.aspx)是最初级的。 被成为rpc 为不同的资源命名可以继续升级。
用http verb(DELETE /user/1)而不是action code(GET /user?action=delete&id=12) — 被称为rpc-hybrid —又可以升。

在REST被炒起来后,这两者就开始逐步被接受了。后续还有继续升级的地方,就是前面提到的HATEOAS,还有code-on-demand。

rpc的问题是不同的rpc提供者使用的协议不同。 影响互通性。 这是官方回答。
居心叵测地推敲。。。 也许还有另一些原因在里面。。。
http是被设计为应用层协议的, 而各种rpc将它当作传输层协议使用, 于是设计者们不高兴了, 就站出来说: http不是你们这样用的。


相比是rpc还是uri, 感觉http verb的理由更明显一些。 它直接使用http本身的语义。
GET,HEAD,OPTIONS是safe的, 是可以随意发送的, 甚至在用户没有明确操作的情况下。(Chrome在地址栏里补全的时候就会发)
PUT,DELETE是unsafe且idempotent的。 虽然不能随意发, 但确实想发的情况下就可以重复发。。。 尤其是在网络这种不可靠的环境下。 失败后简单retry即可。
最复杂的,不安全且不幂等的就留给POST了。
已经发现一些http客户端(浏览器,浏览器插件,http库)会在用户没有确认的情况下发送GET或者连续发送多个GET然后取一个返回。
GET /user?action=delete&id=12 就完蛋了。
如果http客户端敢在用户没有明确指出的情况下发送unsafe methods,应该可以算bug。
而如果在用户明确指出的情况下,没留意到idempotent methods会重复发送的情况。


而HATEOAS和code-on-demand想解决的问题是server与client解偶。
server满足了addressability和uniform interface之后, client应该从哪里知道这些addressable uri在哪? 至于支持那些操作倒是可以用OPTIONS。
从一个文档页面里找? 如果uri有过改动? 文档是否有同步的更新? 以及之前的客户端的代码又该怎么更新?
而HATEOAS是想让REST提供者满足Connectedness,让client可以从REST app的根开始寻找REST提供了那些resources。
在Hypermedia不足以满足需要的时候还可以产生代码让client去执行。。。

REST APIs must be hypertext-driven
A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. The transitions may be determined (or limited by) the client’s knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly (e.g., code-on-demand). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]


回过头来想想。。。  满足这些条件的不就是一个website么不就是一个website么不就是一个website么。。。
感觉restful就是从http/html/website里总结出了一些东西,指导如何写一个好的网站。 然后摇身一变就挂了个service的名。。。

上面这些条件对一个human consumer来说是很好的。 尤其是最后的HATEOAS与code-on-demand。
人类可以通过搜索或者别人的推荐从一个url直接跳转到网站的某个资源, 也可以从网站的根开始一步一步通过链接、表单、AJAX等等寻找他想要的资源。
在网站结构改变后人也有能力(或者说被迫)使用新的url。 producer和consumer完全解耦。 网站说变就变了, 人自己去找吧。

但如果是打算作为programmable service,要让machine consumer也能理解HATEOAS和code-on-demand就没这么容易了。

因此真正的REST evangelist是不推荐使用json的。 比如github的api就带了很多links。 但要解读它们需要github-specific的方法。
他们推荐使用xml,因为xml有一些官方的micro format。 如果这些micro format足够流行就会对machine consumer理解REST app以及REST app之间的互通有帮助。
现实情况是。。。 这些micro format不流行。。。 xml也逐步开始退出流行。。。

总之,这就是我理解的Roy Fielding以及REST evangelist所想的东西。 至于它是否实际、是否会流行甚至传承下去? 可以与Alan Kay之于OO作个比较。。。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
46 [报告]
发表于 2014-03-24 02:48 |只看该作者
starwing83 发表于 2014-03-24 02:16
反正总的来说,你觉得纠结还不是因为SQL功能太强了么= =你要是用不到那些超级功能那关那些干嘛= =


嗯,纠结的就是这点。 那些超级功是因为没有遇到复杂的需求才没用上? 还是因为一开始就是这么考虑的,所以下意识地将那些复杂需求给排除掉或者转换成独立object进行操作?
总之就是缺经验。

starwing83 发表于 2014-03-24 02:16
恩,所以你说对了,的确就是只解决80%问题的


那其实这样也行。。。 能轻松一些是一些。。。

starwing83 发表于 2014-03-24 02:19
哪天要是捐我一台服务器什么的我再去改改……

捐了服务器还改? 正好用来横向扩展。。。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
47 [报告]
发表于 2014-03-24 03:11 |只看该作者
回复 46# OwnWaterloo


    好吧= =去碎觉了= =明天据说要出版本(出来的概率跟找到马航其实差不多吧)所以嘛= =

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
48 [报告]
发表于 2014-03-24 04:38 |只看该作者
回复 44# starwing83

关于JS。 我也没时间去看。。。  只是现在有Lutz顶着于是我就没压力了。。。

关于那两点,我觉得后一句改成: 所有资源都都可以用统一的动词 — GET,HEAD,PUT,DELETE,POST,OPTIONS —去操作。 更合适一些。
没有findItem和findItems,findItemsWhenMatch等不同的动词, 而是用资源来代表单一对象GET /post/ID,集合对象 GET /post,算法(filter) GET /post?after=yesterday 等等。
至于资源是否支持那是资源说了算。 可以用OPTIONS 查询, 可以返回405并给出Allowed, 可以返回404代表这个资源根本不存在。

关于state。  以ftp服务和一个支持上传删除的http文件服务器作为对比。

服务器上肯定是有状态的 —— 目前有哪些文件。 这个状态也是可以改变的 —— 同上传和删除。
RWS里把这个叫做server state。

ftp连接后,可以认证、改变当前目录,列出当前目录,列出当前目录里的文件,下载/上传/重命名/删除文件,创建删除目录等等。
后面那些命令都与认证已经当前目录这两个状态有关。这两个状态会保持到连接断开为止。

而http协议是无状态的。每一个请求都必须包含认证和打算操作的文件的全路径这两个状态,服务器才有足够的信息来完成这个请求。
RWS里把这个叫做application state。 REST api的消费者(application)的状态。

REST application每次都必须把自己的state传递给server,让server有足够的信息完成请求。 这个请求可能会影响server state(unsafe methods)也可能不会(safe methods)。
假设这样实现一个支持匿名用户操作的http文件服务器:
1. GET /files/path/to。 如果 /path/to 是一个文件,就在header里放置相应的content-type,content-length,并且将文件内容放到body里作为响应。 而如果是一个目录,就返回405 Method Not Allowed。
同样还可以通过HEAD查询文件的元信息而并不下载文件。
这两种请求必须将application state —— /path/to 传递给服务器。 但不会影响服务器的状态。
2. PUT /files/path/to 。 上传文件。 如果该路径是一个目录就405 Method Not Allowed。
3. PUT /files/path/to/ 。 创建目录。 如果该路径是一个文件就405 Method Not Allowed。
4. DELETE /files/path/to 。 删除文件或目录。
后面几个如果成功都会影响server state。


问题是这样的api即使是curl消费起来都很困难。。。 至少得有ls功能吧?
于是GET /files/path/to 如果是目录的话, 就可以给出这个目录下的文件和子目录的链接。 于是curl或者浏览器就知道存在哪些资源(文件)以及怎么转换到另一个application state去产生相应的request。
浏览器进入一个目录之后地址栏就会有相应的改变,以显示出当前的application state的一部分。 展示出的链接都是可以转换到的其他的application state。
同时还可以继续带上form表单以引导用户提交或删除文件 —— 同样是转换到其他的application state。 提倡REST的人同时也希望form这种hypermedia能被程序理解 —— 可以这样上传、删除文件哦。

继续假设现在要添加认证功能。 初始的application state里不包含Authorization这个状态。于是服务器无法获得当前是那个用户这一信息。
假设 /files/anonymous/ 下是允许任何人随便弄的。  对这下面的请求服务器都可以完成。
而如果对这之外的请求, 服务器发现没有Authorization时就可以返回401 Unauthorized并带上WWW-Authenticate。
浏览器就会弹出一个丑陋的框, 要求用户输入账户名与密码。 之后浏览器继续发送上一个application state以及新增加的Authorization到服务器。
这下服务器就有足够的信息判断该用户是否有足够的权限访问。 并根据授权规则显示部分允许被操作的资源的链接。
通过这种方式REST就让application添加了新的Authorization状态。 只是这个状态不容易消除。。。
同样, 提倡REST的人希望401和WWW-Authenticate能被程序理解。

starwing83 发表于 2014-03-24 02:28
那么按照你说的,我是不是可以这么理解S,所谓状态就是:资源的表示能提供访问更多操作的可能性?
也就是说,我不知道有多少用户,我GET /user,得到一个列表,这样我就能对我获取的用户进行操作了——因此状态(就有机会)改变了?不然我就只知道这一个接口,谈不上能改变状态。
这么说,S其实说的不是状态,而是【获取可以进行其他操作的必要信息】,是这个理解么

按我目前的理解, http request里所包含的让服务器足够区别是谁打算做什么操作的信息应该算application state。
上面的例子中还有很多request里的信息是server暂时不感兴趣的。 它们算不算application state就不知道了。

对资源请求产生的representation里可以包含改变application state的方式。 比如link, form, 401等等。
GET /user 里, GET和 /user 应该都是application state。 返回一个列表, 里面的链接就可以引导消费者 GET /user/sw 或 GET /user/ow , 于是application state就从 GET /user 转换到了后两者之一。

资源的表示能提供迁移到其他application state的可能性。
GET /user 可以得到一个列表, 因此application state就有机会改变 —— 就可以请求特定的某个用户。
不然只知道 /user 就不知道应该怎么获取特定的user。 就像最开始那个不支持ls的http文件服务器一样。
"获取可以进行其他操作的信息"就是HATEOAS的内容,这些信息可以引导application 进入其他的S,并将S传递给服务器。


关于token。
假设一开始的application state里是没有的。 当访问了一个需要权限的资源时就会引导用户认证, 然后让application添加这个state。
比如认证成功后在header里加一个 Set-Cookie: token=sw;   暂时抛开安全性问题。。。
于是后续的请求就会发送 Cookie: token=sw。 服务器就知道这是谁在发送请求, 并能根据这点进行授权。
服务器里没有和token相关的记录, 每次请求都必须把这个Cookie重新发送。

而另一种做法。 认证成功后在header里添加一个 Set-Cookies: {J,PHP,...}SESSION_ID=random_key。
同样后续的请求会有 Cookie: PHPSESSION_ID=random_key。 服务器也可以通过random_key查询一个lookup table获得该SESSION里的数据,比如user。
于是RWS(不太记得到底是不是这本书里这么说的,还是其他地方)就分情况了。。。
如果lookup table是服务器内存里的一个数据结构, 那这就是将application state(哪个用户发起的请求)放在了server state里。

这样的区分确实有好处。  假设有多个logic server。
前一种 Cookie: token=sw的方式, load balancer无论将它转发到哪个logic server都是可以工作的。 并且每一个logic server都是crash only。 挂了后重启就是。
而后一种 Cookie: PHPSESSION_ID=random_key 的话, load balancer就需要支持session stick。 比如另外添加一个 Set-Cookie: server=1。 然后根据传回的Cookie: server=1将这个请求继续转发回server1。
或者修改PHPSESSION_ID为S1PHP_SESSION_ID,然后根据它选择server1后又改回PHPSESSION_ID。
同时,如果server1挂了, 之前粘着在server1上的用户的登录状态就一起挂了。
也就是说前一种方式每个请求与每个服务器之间没有亲缘性, 而后一种就会有。

但有时候一些机密的东西不能发回到客户那里。。。 于是RWS松口了。。。
说在这种情况下,不要把那个lookup table放在逻辑服务的内存里。。。 应该放在持久化存储里。。。 比如数据库或redis(开启持久化机制)之类的东西里。。。

总之。。。 No Silver Bullet。。。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
49 [报告]
发表于 2014-03-24 04:57 |只看该作者
本帖最后由 OwnWaterloo 于 2014-03-24 04:59 编辑

回复 44# starwing83

虽然和web开发有关。。。 但貌似和楼顶的书没关系了。。。  于是又跑题这么多楼?
最后跑一帖。。。 关于session stick。。。 这应该是从RWS里最大的收获之一。 另一个可能是http verb,方法的安全与幂等。 其他的,感觉必须照着这样做的理由还不够充分。。。

这完全改变了我一开始的一个想法。。。
网站不是可能会有一些需要多个交互步骤才能完成的流程嘛。。。
第1步完成一些工作,然后将后续需要的状态放到session里。 后续步骤继续从session里读,然后可能会添加更多的状态。 最后完成它。。。
编写GUI时这种人肉维护之前的状态的方式已经受够了。。。  现在知道coroutine和continuation后总不会这么苦逼了吧?
看了RWS以及类似The twelve-factor的文章之后彻底傻了。。。
它们说得有道理。。。 于是我再也不提coroutine或continuation之于web开发了。。。 除非能将它们序列化和反序列化。。。

而随后关于session stick的想法还在继续转变。。。  因为NoSQL的关系。。。
relational database(或者说支持强一致性的存储)不是扩展起来很麻烦嘛。。。  于是有eventually consistent的存储。。。
一旦用了它。。。 那又需要session stick了。。。 虽然需求可能不如Cookie: SESSION_ID=random_key 这样强。。。

等有多步交互或eventually consistent存储的需要时再说。。。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
50 [报告]
发表于 2014-03-24 14:35 |只看该作者
回复 49# OwnWaterloo


    妈的,鼠标没电了,恢复的数据没了,我回了好多字的= =

不管了,晚上再说好了= =
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP