CuriousY A world with wonder

GraphQL简单实践

| Comment

之前就简单接触过GraphQL,但一直没怎么上手实践。最近想用GraphQL来做后端的API层,正好可以真正地用一用了。

以下所有代码均为使用GraphQL的JavaScript的SDK。

Server side

GraphQL官方提供了一个express插件可以很方便地在express的基础上构建GraphQL API:

var express = require('express');
var graphqlHTTP = require('express-graphql');

var app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));
app.listen(4000);

其中,graphqlHTTP接收了三个参数,graphiql: true表示会提供一个方便查询的GraphQL的前端界面,否则只有纯后端的API。另外两个参数后面会详细讲一讲。

GraphQL Schema

GraphQL自创了一套schema的语法,通过graphql.buildSchema函数可以将这套语法进行解析并生成JavaScript中对应的数据结构:

var {buildSchema} = require('graphql');

var schema = buildSchema(`
  input MessageInput {
    content: String
    author: String
  }

  type Message {
    id: ID!
    content: String
    author: String
  }

  type Query {
    getMessage(id: ID!): Message
  }

  type Mutation {
    createMessage(input: MessageInput): Message
    updateMessage(id: ID!, input: MessageInput): Message
  }
`);
Read more

记一次DOM事件无法触发的坑

| Comment

接手一个项目,前端用codemirror来展示了一段代码,我想添加一个鼠标点击某一行的事件,却发现怎么都不会调用我绑定的关于click事件的函数。

html事件触发的机制###

与其抓破脑袋想为什么没有触发绑定的事件函数,不妨先想想有哪些方式可以让绑定的事件函数失效。

首先,根据W3C标准,DOM事件触发分为了三个阶段:

The standard DOM Events describes 3 phases of event propagation:

  1. Capturing phase – the event goes down to the element.
  2. Target phase – the event reached the target element.
  3. Bubbling phase – the event bubbles up from the element.

Here’s the picture of a click on <td> inside a table, taken from the specification:

img

讲得更具体一些,以冒泡阶段(bubbling phase)为例,当一个DOM元素触发了一个事件时,首先,该元素对应该事件的处理函数会被调用(如果有的话),然后,该事件会继续传播(或者称之为冒泡(bubbles up))到该元素外层的DOM元素中,并触发其对应的处理函数,以此类推。

因此,大胆推测,我们可以有这些方式来阻止事件函数的触发:

  • 在事件“传递”路径上进行劫持,即在上述某个阶段阻止事件进一步传递到目标元素,但副作用是“传递”过程被截断了,目标元素之后的元素也无法获知该事件的存在了。
  • 在目标元素本身的事件触发之前进行劫持,不清楚是否存在这样的接口,可以在目标元素事件真正触发之前进行操作,并且不影响事件的继续“传递”。
  • 取消绑定目标元素的事件函数,但取消绑定之后是不是还需要再在适当的时候绑定回来?这种方式感觉比较蠢。
Read more

关于Groovy和Jenkins shared library

| Comment

最近工作需要把一部分Jenkins 1.x上的job迁移到Jenkins 2.0上,这里简单写点感受和一些需要注意的地方。

Jenkins 2.0首先是完全兼容Jenkins 1.x的,因此迁移的成本并不大。其次,Jenkins 2.0主打的一个特性叫做pipeline,你可以理解为把原先在网页上各种地方存放的代码集中到了一个代码中(主要是Groovy代码)。所有和流程相关的东西(比如准备执行代码的运行环境、安装依赖等步骤)都可以放在pipeline代码中,因此一个Jenkins job的设置就简化为了输入参数+pipeline代码。而由于不同的Jenkins job的pipeline其实有很多代码是通用的,所以就有了shared library一说,即把通用的代码放在一个git repo中,配置好后Jenkins会定期地拉其中的代码,因此我们在pipeline中就可以引入并调用其中的代码了。

关于Groovy

Groovy是Java编译器可以直接编译运行一种脚本语言,因此向Jenkins这种用Java写的软件就喜欢用它来作为DSL。因为是脚本语言,它本身并不复杂,只要使用过其他的脚本语言是很容易上手的。这里提几点对于我这种之前用惯了Python和JavaScript的人要注意的地方:

  • Groovy中使用def关键字来声明变量,即类似JavaScript中的var

  • Groovy中的list和dict(Groovy中称为Map)数据类型都是用中括号表示的,只不过dict中会有冒号表示key value pair:

    def listA = [1, 2, 3]
    def dictA = ['a': 1, 'b':2]
    def emptyList = []
    def emptyDict = [:]
    
  • Groovy中的函数的输入可以不用括号括起来,而直接用空格间隔开函数名和参数(并且参数和对应的输入之间是用冒号而不是等号):

    // below two are the same
    myFunc paramA: inputA, paramB: inputB
    myFunc(paramA: inputA, paramB: inputB)
    
  • Groovy中使用字符串模板时,下面两种都是可以的,对于复杂的数据结构最好使用后者(外面加花括号):

    def name = 'Cook'
    def str1 = 'My name is $name'
    def str2 = 'My name is ${name}'
    
Read more

Stateless component and react-redux

| Comment

在React中引入Redux的一大好处就是将组件的状态移出来,这样React组件就变成了纯View层的对象,可以专心只做View相关的事情了,是所谓“低耦合”。那么,既然React组件不存储状态了, 是否可以将原先的组件都替换为无状态的函数组件呢?

Use stateless component with react-redux

尝试一下,便知行不行:

App.js:

import React from 'react';

const App = (props) => {
    return (
        <div className="App">
            <input type="text" onChange={props.handleInputChange} value={props.input} />
        </div>
    );
};

export default App;

container.js:

import {connect} from 'react-redux'
import App from './App'

const mapStateToProps = (state, ownProps) => {
    return state;
};

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        handleInputChange: (event) => {
            dispatch({type: 'INPUT_CHANGE', value: event.target.value});
        }
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(App);
Read more

关于JavaScript的原型链和继承

| Comment

之前看了《You don’t know JS》系列,对原型链这块一直没理解透,这里再探讨下JavaScript中的原型链,以及怎样使用原型链达到类的继承的效果。

原型链##

__proto__###

原型链可以理解为一个单向链表,JavaScript中每个对象都拥有一个__proto__属性,它指向的就是该对象的原型链(的链表头)。顺着原型链往下找,总是能找到一个链尾,它的值是null

var a = {a: 1};
console.log(a.__proto__);  // {}
console.log(a.__proto__.__proto__);  // null

var b = function () {
    return 'b';
};
console.log(b.__proto__);  // [Function]
console.log(b.__proto__.__proto__);  // {}
console.log(b.__proto__.__proto__.__proto__);  // null

原型链中的每一个节点都指向了某个对象的原型(prototype),比如接着上面的代码:

console.log(a.__proto__ === Object.prototype);  // true
console.log(b.__proto__ === Function.prototype);  // true
console.log(b.__proto__.__proto__ === Object.prototype);  // true

var c = {c: 3};
console.log(c.__proto__ === a.__proto__);  // true

可以看到:

  • 同一个类型的对象共享同一个原型链(比如上面的ac);
  • 不同类型的对象可以共享“某一段”原型链(比如上面的b.__proto__a);
Read more
| Page 8 of 25 |