โปรแกรมมิ่ง

Quartz Scheduler มันคืออะไร การใช้งานเบื้องต้น

Quartz Scheduler เป็น Open Source Project นิยมนำมาใช้งานกับโปรเจคระดับองค์กร ทำหน้าที่เป็นเครื่องมือจัดการเรื่อง Job Scheduler คล้ายกับ Cron ในระบบปฏิบัติการ linux ช่วยจัดการเรื่อง Job ที่มีการทำงานตั้งแต่ 1 Process ขึ้นไปใช้กับงาน Process ที่ต้องใช้เวลาในการ Processing ยาวนานกินเวลาหลายชั่วโมง ภายใน quartz-scheduler จะมี Class CronTrigger ซึ่งช่วยทำหน้าที่จัดการเวลาการทำงาน เช่น “ตอน 8.00 น.ทุกวันจันทร์ถึงวันศุกร์” หรือ “เวลา 1.30 น. ทุกวันศุกร์สุดท้ายของเดือน” ช่วยเพิ่มประสิทธิภาพการจัด scheduler ได้ออย่างดี

เริ่มต้นการใช้งาน

เพิ่ม dependency ในไฟล์ pom.xml

<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>1.8.6</version>
</dependency>

สร้าง Class Job Execute

public class DumbJob implements Job{

  public void execute(JobExecutionContext arg0) throws JobExecutionException {
    System.out.println("Poolsawat.com Run Scheduler Job");		
  }

}

ตัวอย่าง ตั้งเวลาการทำงานทุกนาที โดยเริ่มทำงานตอนทำงานในนาทีถัดไปหลังจากสั่งเริ่มการทำงาน

try {	
  SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
  
  Scheduler sched = schedFact.getScheduler();

  sched.start();

  JobDetail jobDetail = new JobDetail("myJob", null, DumbJob.class);

  Trigger trigger = TriggerUtils.makeMinutelyTrigger();
  trigger.setStartTime(TriggerUtils.getEvenMinuteDate(new Date()));
  trigger.setName("myTrigger");

  sched.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
  e.printStackTrace();
}

ตัวอย่าง ตั้งเวลาการทำงานช่วงเวลา 00:00 น. โดยเริ่มทำงานทันที่

try {
  SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

  Scheduler sched = schedFact.getScheduler();

  JobDetail jobDetail = new JobDetail("myJob",
      Scheduler.DEFAULT_GROUP, 
      DumbJob.class);
  
  Trigger trigger = TriggerUtils.makeDailyTrigger(0, 0);
  trigger.setStartTime(new Date());
  trigger.setName("myTrigger");

  sched.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
  e.printStackTrace();
}

สร้าง Class Job ที่รับ Parameter

public class DataMapJob implements Job{
  public void execute(JobExecutionContext context) throws JobExecutionException {
    JobDetail detail = context.getJobDetail();
    JobDataMap mapData = detail.getJobDataMap();		
    System.out.println("param1 ::=="+mapData.getString("param1"));
    System.out.println("param2 ::=="+mapData.getString("param2"));
  }
}

ตัวอย่าง การส่งค่า Parameter เข้า Process ภายใน Class Job

try {
  SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

  Scheduler sched = schedFact.getScheduler();

  sched.start();

  JobDetail jobDetail = new JobDetail("myJob", null, DataMapJob.class);
  
  
  JobDataMap dataMap = new JobDataMap();
  dataMap.put("param1", "poolsawat.com");
  dataMap.put("param2", "quartz");
  jobDetail.setJobDataMap(dataMap);
  
  Trigger trigger = TriggerUtils.makeMinutelyTrigger();
  trigger.setStartTime(TriggerUtils.getEvenMinuteDate(new Date()));
  trigger.setName("myTrigger");

  sched.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
  e.printStackTrace();
}

ตัวอย่าง ตั้งค่าใน Job ทำงานแค่ครั้งเดียว

try {
  SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

  Scheduler sched = schedFact.getScheduler();

  sched.start();

  JobDetail jobDetail = new JobDetail("myJob", null, DataMapJob.class);
  
  SimpleTrigger trigger = new SimpleTrigger("myTrigger",
      null,
      new Date(),
      null,
      0,
      0L);
  
  sched.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
  e.printStackTrace();
}

เพิ่มเติม…

Gson Open Source Library สำหรับจัดการ JSON Formatter

“JSON” ไม่ใช่เรื่องใหม่อะไร เพราะปัจจุบันมีการใช้งานกันอย่างแพร่หลาย สำหรับเอาไว้ใช้จัดการข้อมูลรับส่งระหว่าง frontend และ backend เพราะด้วยความง่ายและดูเป็นมาตฐาน มีรูปแบบที่ตายตัว ที่ใคร ๆ ก็สามารถเข้าใจได้เพราะเป็นการเก็บข้อมูลแบบ Key และ value

Java Library ที่ใช้สำหรับจัดการ JSON Data ก็มีมากมายให้ได้เลือกใช้งาน เช่น Google-Gson Library ,Flexjson ,Json-io ,Genson ,JSONiJ ,Jackson ,JSON-lib เป็นต้น ผมเองเป็นคนนึงที่นิยมใช้งาน Library ที่เป็น Open Source และต้องมีกลุ่ม Community ที่ใหญ่ และ Gson เองก็ได้รับความนิยมมาก เพราะด้วยความง่ายในการใช้งาน

การเริ่มใช้งาน Gson

เพิ่ม dependency

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.6.2</version>
</dependency>




การใช้งานเบื้องต้นของ Gson จะมีด้วยกัน 2 รูปแบบ ด้วยกัน คือ Serialization ,Deserialization

Serialization การแปลงข้อมูลที่อยู่ในรูปแบบ Object ไปเป็น Json String Format

Gson gson = new Gson();
gson.toJson(1);            // ==> 1
gson.toJson("abcd");       // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };
gson.toJson(values);       // ==> [1]

Deserialization  การแปลงข้อมูลในรูปแบบ Json String Format ไปเป็น Object

int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);

ตัวอย่างการใช้งานง่าย ๆ

สร้าง POJO Class

public class EasyObject {
    private String valueString;
    private int valueInteger;
    private Date valueDate;
    private boolean valueBoolean;
    // getter , setter

    @[email protected] public String toString() { return "EasyObject [valueString=" + valueString + ", valueInteger=" + valueInteger + ", valueDate=" + valueDate + ", valueBoolean=" + valueBoolean + "]"; }
}

ตัวอย่าง Method Serialization

private void exampleSerialization(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  //Serialization 
  System.out.println("serialization :: "+new Gson().toJson(easy));  
}
/*
serialization :: {"valueString":"poolsawat.com","valueInteger":999,"valueDate":"Oct 4, 2017 9:35:34 PM","valueBoolean":true} 
*/

ตัวอย่าง Method Deserialization

private void exampleDeserialization(){
  String json = "{\"valueString\":\"poolsawat.com\",\"valueInteger\":999,\"valueDate\":\"Oct 4, 2017 9:30:08 PM\",\"valueBoolean\":true}";
  EasyObject easy = new Gson().fromJson(json, EasyObject.class);
  System.out.println("deserialization :: "+easy.toString());  
}
/* 
deserialization :: EasyObject [valueString=poolsawat.com, valueInteger=999, valueDate=Wed Oct 04 21:30:08 ICT 2017, valueBoolean=true] 
*/

เมื่อใช้งาน Gson ไปสักระยะก็จะพบปัญหา หรือ สิ่งที่อยากปรับแต่งกับข้อมูลผลลัพธ์ให้เป็นไปตามความต้องการ Gson เองก็มี  GsonBuilder Class สำหรับให้เอาไว้ Custom Serialization and Deserialization

ตัวอย่างการแสดงผลลัพธ์ทาง Console ให้อยู่ในรูปแบบที่สวยงานโดยการ กำหนด PrettyPrinting

private void examplePrettyPrinting(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  //Serialization 
  Gson gson = new GsonBuilder().setPrettyPrinting().create();		
  System.out.println("serialization :: "+gson.toJson(easy));
}

/*
serialization :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "valueDate": "Oct 4, 2017 9:54:58 PM",
  "valueBoolean": true
}*/

ตัวอย่างต้องการ custom field ที่มี value เป็น null อยากที่จะให้แสดงผลลัพธ์ field ที่เป็น null นั้นออกมาด้วยจำเป็นต้องกำหนด ให้  .serializeNulls()

private void exampleSerializeNulls(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  //easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  
  //Serialization exclude null
  Gson gson = new GsonBuilder().setPrettyPrinting()				
      .create();		
  System.out.println("serialization exlude null:: "+gson.toJson(easy));
  
  //Serialization exclude null
  gson = new GsonBuilder().setPrettyPrinting()				
      .serializeNulls()
      .create();		
  System.out.println("serialization want null :: "+gson.toJson(easy));
}
/*
serialization exlude null:: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "valueBoolean": true
}
serialization want null :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "valueDate": null,
  "valueBoolean": true
}*/




หากต้องการที่จะกำหนดชื่อใหม่ให้กับ key name ก็สามารถทำได้ โดยไม่ด้วยกัน 2 วิธี คือการกำหนดผ่าน annotation @SerializedName และ anonymous inner type การ setFieldNamingStrategy

@SerializedName("rename_valueBoolean") // เพิ่มเข้า
private boolean valueBoolean;

private void exampleRenameFieldKeyWithAnnotation(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  //easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  
  Gson gson = new GsonBuilder().setPrettyPrinting()					
      .create();		
  System.out.println("serialization :: "+gson.toJson(easy));
}
/*
serialization :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "rename_valueBoolean": true
}
*/

private boolean valueBoolean; // ไม่ต้องมี annotation แล้ว

private void exampleRenameFieldKeyWithAnonymous(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  //easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  
  Gson gson = new GsonBuilder().setPrettyPrinting()		
      .setFieldNamingStrategy(new FieldNamingStrategy() {
        
        public String translateName(Field f) {
          if (f.getName().equals("valueBoolean"))
            return "rename_valueBoolean";
          else
            return f.getName();
        }
      })
      .create();		
  System.out.println("serialization :: "+gson.toJson(easy));
}

/*
serialization :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "rename_valueBoolean": true
}
*/

สำหรับการกำหนดรุปแบบ format ให้ field ที่เป็น type date ก็สามารถกำหนดให้ได้ด้วยการกำหนด setDateFormat ตาม format ที่เรากำหนดเองได้เลย

private void exampleDateFormat(){
  EasyObject easy = new EasyObject();
  easy.setValueBoolean(true);
  easy.setValueDate(new Date());
  easy.setValueInteger(999);
  easy.setValueString("poolsawat.com");
  
  Gson gson = new GsonBuilder().setPrettyPrinting()		
      .setDateFormat("dd/MM/yyyy HH:mm:ss")
      .create();
  System.out.println("serialization dd/MM/yyyy HH:mm:ss :: "+gson.toJson(easy));		
  
  gson = new GsonBuilder().setPrettyPrinting()		
      .setDateFormat("yyyy/MM/dd")
      .create();
  System.out.println("serialization yyyy/MM/dd :: "+gson.toJson(easy));		
}
/*
serialization dd/MM/yyyy HH:mm:ss :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "valueDate": "04/10/2017 22:29:53",
  "rename_valueBoolean": true
}
serialization yyyy/MM/dd :: {
  "valueString": "poolsawat.com",
  "valueInteger": 999,
  "valueDate": "2017/10/04",
  "rename_valueBoolean": true
}
*/

ในบางครั้งเราก็ไม่ต้องการสร้าง POJO สำหรับการเก็บ Data ชุดใหม่ Gson ก็มี Class สำหรับสร้าง Json Object เองได้สำหรับคนที่อยากกำหนด key ที่หลากหลาย

private void exampleJsonObject(){
  JsonObject object = new JsonObject();
  object.addProperty("blog_title", "Gson Open Source Library สำหรับจัดการ JSON Formatter");
  object.addProperty("blog_content", "“JSON” ไม่ใช่เรื่องใหม่อะไร เพราะปัจจุบันมีการ...");
  object.addProperty("blog_date", "04/10/2017");
  object.addProperty("blog_author", "poolsawat apin");
  Gson gson = new GsonBuilder().setPrettyPrinting().create();		
  System.out.println("serialization JsonObject :: "+gson.toJson(object));		
}
/*
serialization JsonObject :: {
  "blog_title": "Gson Open Source Library สำหรับจัดการ JSON Formatter",
  "blog_content": "“JSON” ไม่ใช่เรื่องใหม่อะไร เพราะปัจจุบันมีการ...",
  "blog_date": "04/10/2017",
  "blog_author": "poolsawat apin"
}
*/

อยากสร้างในรูปแบบของ Json Array ก็สามารถทำได้

private void exampleJsonArray(){
  JsonArray array = new JsonArray();
  
  JsonObject object1 = new JsonObject();
  object1.addProperty("blog_title", "Gson Open Source Library สำหรับจัดการ JSON Formatter");
  object1.addProperty("blog_content", "“JSON” ไม่ใช่เรื่องใหม่อะไร เพราะปัจจุบันมีการ...");
  object1.addProperty("blog_date", "04/10/2017");
  object1.addProperty("blog_author", "poolsawat apin");
  array.add(object1);
  
  JsonObject object2 = new JsonObject();
  object2.addProperty("blog_title", "สร้าง Spring MVC 4 ร่วมกับ Apache Tiles 3");
  object2.addProperty("blog_content", "สำหรับงานพัฒนาเว็บไซต์ด้วยภาษา Java มี Frameworks ให้เลือกอย่างมากมาย ...");
  object2.addProperty("blog_date", "15/09/2017");
  object2.addProperty("blog_author", "poolsawat apin");
  array.add(object2);
  
  Gson gson = new GsonBuilder().setPrettyPrinting().create();		
  System.out.println("serialization JsonArray :: "+gson.toJson(array));					
}
/*
serialization JsonArray :: [
  {
    "blog_title": "Gson Open Source Library สำหรับจัดการ JSON Formatter",
    "blog_content": "“JSON” ไม่ใช่เรื่องใหม่อะไร เพราะปัจจุบันมีการ...",
    "blog_date": "04/10/2017",
    "blog_author": "poolsawat apin"
  },
  {
    "blog_title": "สร้าง Spring MVC 4 ร่วมกับ Apache Tiles 3",
    "blog_content": "สำหรับงานพัฒนาเว็บไซต์ด้วยภาษา Java มี Frameworks ให้เลือกอย่างมากมาย ...",
    "blog_date": "15/09/2017",
    "blog_author": "poolsawat apin"
  }
]
*/

เหล่านี้เป็นตัวอย่างการใช้งานเบื้องต้นส่วนหนึ่งเท่านั้น มี UserGuide ให้ได้เข้าไปดูวิธีการใช้งานเพิ่มเติมได้

สร้าง Spring MVC 4 ร่วมกับ Apache Tiles 3

สำหรับงานพัฒนาเว็บไซต์ด้วยภาษา Java มี Frameworks ให้เลือกอย่างมากมาย เช่น JSF ,Vaadin ,GWT เป็นต้น และอีก 1 Framework ที่ได้รับความนิยมไม่แพ้ตัวอื่น ๆ เลยก็เป็น Spring MVC

ปัญหาที่ต้องเจอสำหรับงานพัฒนาเว็บคือการเรียกใช้งาน js,css ที่เป็น plugins มากมายก่ายกอง และเว็บไซต์ 1 เว็บก็ไม่ได้มีแค่หน้าเดียวซะเมื่อไหร่ละ เกิดความซ้ำซ้อนในการเรียก import js,css เข้ามาในแต่ละ page ดีหน่อยก็ทำไฟล์ include_js_css.jsp สำหรับทำหน้าที่ import js,css และเมื่อต้องการเรียก plugins js,css ก็ import include_js_css.js เข้ามา ก็พอจะแก้ปัญหานี้ให้ผ่านไปได้แต่ก็ยังไม่ถือว่าเป็นมือโปรสักเหล่าไหร่ และก็ทำให้การเขียนโค๊ดดูไม่สะอาดตาเอาซะเลย

เพราะว่า Spring MVC ปัจจุบันเวอชั่น 5 เข้าไปแล้ว ปัญหาเรื่องที่กล่าวมานี้ก็ย่อมได้รับการแก้ไขแล้ว วันนี้ก็เลยอยากจะนำพามาให้รู้จัก Apache Tiles ทำให้การจัดการไฟล์ view ทั้งหลายในเว็บของเราดูเป็นระเบียบเรียบร้อยยิ่งขึ้น เริ่มกันเลย

ก่อนอื่นสร้าง Maven Project ขึ้นมา ทำการเพิ่มใน pom.xml

<properties>
    <tiles.version>3.0.7</tiles.version>
    <spring.version>4.0.1.RELEASE</spring.version>
</properties>
<dependencies>
  <!-- Apache Tiles -->
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-core</artifactId>
    <version>${tiles.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-core</artifactId>
    <version>${tiles.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-api</artifactId>
    <version>${tiles.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-servlet</artifactId>
    <version>${tiles.version}</version>
  </dependency>
  <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-jsp</artifactId>
    <version>${tiles.version}</version>
  </dependency>


  <!-- -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
  </dependency>

  <!-- Spring dependencies -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>

</dependencies>

เพิ่ม code ใน web.xml

<servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

สร้างไฟล์ dispatcher-servlet.xml ใน WEB-INF/

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <context:component-scan base-package="com.poolsawat" />


  <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
    <property name="definitions">
      <list>
        <value>/WEB-INF/tiles/tiles-template.xml</value>
        <value>/WEB-INF/views/tiles-views.xml</value>
      </list>
    </property>
  </bean>

  <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView" />
  </bean>

</beans>




สร้างชุดไฟล์ tiles สำหรับทำ template

/WEB-INF/tiles/layouts/defaultLayout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><tiles:getAsString name="title" /></title>
</head>
<body>
  <table border="1'" style="width:93%;margin: 30px 50px 30px 50px;">
    <tbody>
      <tr>
        <td colspan="2" style="background-color: orange;"><tiles:insertAttribute name="header" /></td>
      </tr>
      <tr>
        <td style="width:20%;background-color: yellow;"><tiles:insertAttribute name="menu" /></td>
        <td style="width:80%;background-color: blue;"><tiles:insertAttribute name="body" /></td>
      </tr>
      <tr>
        <td colspan="2" style="background-color: pink;"><tiles:insertAttribute name="footer" /></td>
      </tr>
    </tbody>
  </table>
</body>
</html>

/WEB-INF/tiles/template/defaultFooter.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<div style="width:100%;hight:300px;">
  <h1>Footer</h1>
</div>

/WEB-INF/tiles/template/defaultHeader.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<div style="width:100%;hight:300px;">
  <h1>Header</h1>
</div>

/WEB-INF/tiles/template/defaultMenu.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="context" value="${pageContext.request.contextPath}" />
<div style="hight:300px;">
  <ul>
    <li><a href="${context }/hello">Hello</a></li>
    <li><a href="${context }/home">Home</a></li>
    <li><a href="${context }/welcome">Welcome</a></li>
  </ul>
</div>

/WEB-INF/tiles/tiles-template.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
  <definition name="default" template="/WEB-INF/tiles/layouts/defaultLayout.jsp">
    <put-attribute name="header" value="/WEB-INF/tiles/template/defaultHeader.jsp" />
    <put-attribute name="menu" value="/WEB-INF/tiles/template/defaultMenu.jsp" />  
    <put-attribute name="title" value="" />		
    <put-attribute name="body" value="" />
    <put-attribute name="footer" value="/WEB-INF/tiles/template/defaultFooter.jsp" />		
  </definition>	
</tiles-definitions>

ต่อไปสร้าง view สำหรับเป็นหน้า page ของเว็บเรา

/WEB-INF/views/hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h1>Hello Page</h1>

/WEB-INF/views/home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h1>Home Page</h1>

/WEB-INF/views/welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h1>Welcome Page</h1>

/WEB-INF/views/tiles-views.xml

<?xml version="1.0"?>
  <!DOCTYPE tiles-definitions PUBLIC
    "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
    "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
  <definition name="hello" extends="default">
    <put-attribute name="title" value="hello" />
    <put-attribute name="body" value="/WEB-INF/views/hello.jsp" />
  </definition>
  
  <definition name="welcome" extends="default">
    <put-attribute name="title" value="welcome" />
    <put-attribute name="body" value="/WEB-INF/views/welcome.jsp" />
  </definition>
  
  <definition name="home" extends="default">
    <put-attribute name="title" value="home" />
    <put-attribute name="body" value="/WEB-INF/views/home.jsp" />
  </definition>
  
</tiles-definitions>

ไฟล์ tiles-template.xml จะเป็นไฟล์สำหรับ config tiles ว่าจะให้ไปเรียก layouts แต่ละส่วน ในตัวอย่างจะมีการแบ่งหน้าเว็บเป็น 4 ส่วน คือ header , menu , body ,footer

ไฟล์ tiles-views.xml จะถูกใช้งานเป็นตัวกำหนด view ของแต่ละ page จะเรียกนำไฟล์อะไรมาใช้บ้างจะถูกกำหนดที่ไฟล์นี้ definition name จะถูกไปเรียกในการ Mapping กับ Controller

ขั้นตอนต่อไปก็ทำในส่วนของการ mapping controller กับ view

package : com/poolsawat/controller/IndexController.java

package com.poolsawat.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {

  @RequestMapping("/hello")
  public String hello() {
    return "hello";
  }
  
  @RequestMapping("/welcome")
  public String welcome() {
    return "welcome";
  }
  
  @RequestMapping("/home")
  public String home() {
    return "home";
  }
}

ทดสอบโปรแกรม

โครงสร้างเว็บ

Github Source Code ตัวอย่างนี้

[ES6] Promise คืออะไร

พรอมิส (Promise)

ES6 จะมี Object ที่เรียกว่า “พรอมิส” (Promise) เป็นตัวช่วยให้การเขียนโปรแกรมแบบ Asynchronous ทำให้ Source Code ของคุณจัดการได้ง่าย และเป็นระเบียบดียิ่งขึ้น ปัจจุบัน Browser ค่ายดังอย่าง Firefox ,Google Chome ,Safari Support บ้างแล้วแต่จะมีปัญหากับ Browser บางค่ายจะยังไม่ Support อยากใช้จำเป็นต้องผ่านการ compile ผ่าน Compiler ยอดฮิต อย่าง Bebel JS ให้เป็น ES5 ซะก่อน (ติดตามการพัฒนาได้จาก ECMAScript compatibility)

let promise = new Promise( executor );

ตัวอย่างการสร้าง Promise Object ในส่วนของ executor คือค่า function callback ธรรมดาทั่วไปนั้นเอง

function executor_function (resolve ,reject){
    // TODO
}

การประกาศฟังก์ชั่น executor_function จะต้องมี parameter ที่จำเป็น 2 ตัว คือ Resolve , Reject (จะตั้งชื่อเป็นอะไรก็ได้) สนใจแค่ตำแหน่งลำดับ

เนื่องจากคำว่า Promise มีความหมายว่า “สัญญา” ด้วยเหตุผลนี้ในทาง Javascript จะหมายถึงตัวแทน Object ที่ยังทำงานไม่เสร็จแต่ให้คำมั่นว่าจะทำงานเสร็จในอนาคตนั่นเอง




สถานะของ พรอมิส (Promise)

เนื่องจากการทำงานใน Object ที่เป็น Function Callback นั้นผลของการทำงานอาจจะดำเนินการสำเร็จ หรือ ไม่สำเร็จ ดังนั้น Promise เองก็จะมีสถานะที่แตกต่างกันไป โดยแบ่งออกเป็น 3 สถานะ ดังต่อไปนี้

  1. สถานะ Pending (รอก่อน) หมายถึง Promise ยังทำงานไม่เสร็จ
  2. สถานะ Fulfilled (สมหวัง) หมายถึง Promise ที่ทำงานเสร็จแล้ว
  3. สถานะ Rejected (ล้มเลิกไป) หมายถึง Promise ที่ทำงานไม่สำเร็จ ล้มเหลว หรือเกิด Error ระหว่างการทำงาน

Fulfilled และ Rejected จะเรียกรวมกันว่าสถานะ settled (ตัดสินใจ)

เมธอด then()

function callback executor จะมีการประกาศ parameter ไว้ 2 ตัว

function executor(resolve,reject){
    // source code 

    if(success){
       resolve(value); // Line a
    }

    if(failed){
       reject(reason) // line b
    }
}

var promise = new Promise(executor);

promise.then(function lineA(value){
    /*source code */
},function lineB(reason){
    /*source code */
});

เมื่อเรียกใช้งาน function executor ซึ่งเป็นการทำงานแบบ Asynchronous โดย Logic ของโปรแกรม จะ expect ผลเป็น success และ failed ถ้า success จะ return ค่า value ออกไป ผ่าน resolve() แต่ถ้าเป็น failed จะ return ค่า reason ออกไปผ่าน reject() ออกไป โดยที่ .then จะมี parameter function callback 2 function คือ lineA และ lineB หน้าที่ของ function lineA คือจะทำก็ต่อเมื่อค่าที่ได้จาก object promise เป็นการทำงานที่ fulfilled (สำเร็จ) และ function lineB จะทำก็ต่อเมื่อกรณีการทำงานเกิด failed ,error (ไม่สำเร็จ)

เมธอด catch()

เสมือนการเรียกใช้งาน .then ที่เป็นเหตุการณ์ที่ไม่สำเร็จเท่านั้น

promise.catch(function(reason){
      /* rejected */
});

promise.then(null,function(reason){
      /*  reason*/
});

ทั้ง 2 ทำหน้าที่เหมือนกัน
เรียก then() แบบต่อเนื่อง

ปกติเมื่อเราเรียกเมธอด .then() มันก็จะ return Promise ออกมาเสมอโดยไม่ต้องเขียน คำสั่ง return อะไรเลย เราจึงสามารถเรียก .then() ได้อย่างต่อเนื่อง

let p1 = new Promise(function(resolve,reject){
     resolve("success");
});

let p2 = p1.then(function(value){
    console.log('Promise : ',value);
});

let p3 = p2.then(function(){
    console.log('Finish');
});

/* result 
"Promise : success"
"Finish"
*/




ดักจับ error แบบต่อเนื่อง
let promise = new Promise(function(resolve,reject){
     throw new Error('error1');
});

promise.catch(function(error){
     console.log("catch1: ",error.message);
     throw new Error('error2');
}).catch(function(error){
     console.log("catch2: ",error.message);
     throw new Error('error3');
}).catch(function(error){
     console.log("catch3: ",error.message);
});

/* result
"catch1: error1"
"catch1: error2"
"catch1: error3" */
Promise.all()

การเรียกใช้ Promise หลายตัวพร้อมกันก็สามารถทำได้

let p1 = Promise.resolve('Promise1');
let p2 = Promise.resolve('Promise2');
let p3 = Promise.resolve('Promise3');

let p4 = new Promise.all([p1,p2,p3]);

p4.then(function(value){
     console.log(value);
});


/* result 
["Promise1","Promise2","Promise3"] */

# เครดิตจากหนังสือ “พัฒนาเว็บแอปพิเคชั่นด้วย Javascript” โดย คุณ จตุรพัชร์ พัฒนทรงศิวิไล ขอขอบคุณครับสำหรับเนื้อหาสำหรับบทความนี้

เล่าประสบการณ์แข่งขัน Hackathon ครั้งแรกให้ชีวิต

เพิ่งผ่านพ้นไปไปกับงาน PWA Online Hackathon งานสำหรับนักพัฒนาสาย Web ที่จะสร้างสรรค์ผลงานในช่วงแค่ระยะเวลาแค่ 48 ชม. โดยเรียกว่าเปิดโอกาสให้นักพัฒนาทั่วไป ไม่ใช่แค่ภายในประเทศไทยแต่รวมถึงนักพัฒนาทั่วโลก โดยงานถูกจัดขึ้นเมื่อวันที่ 23 มิถุนายน 2560 20:00 น. – 25 มิถุนายน 2560 20:00 น.

PWA Online hackathon คืออะไร

PWA Online Hackathon เป็นการแข่งขัน Hackathon ที่ไม่ต้องมาเจอหน้ากันจริงๆ ต่างคนต่างทำอยู่บ้าน สร้าง Web Application เจ๋ง ๆ แล้วส่งมาแข่งกันผ่าน online Web Application ของใครเจ๋ง ก็รับรางวัลมากมายจากเราไปได้เลย

โดยงานนี้ได้ Sponsor  บริษัทใหญ่ ๆ หลายบริษัท

ของรางวัลเรียกได้ว่าจัดเต็มกันเลยที่เดียว

เมื่อได้สมาชิกในทีมครบ ซึ่งก็เหลือเวลาเตรียมตัวก่อนถึงวันแข่งขันจริง ประมาณ 2 สัปดาห์ ในระหว่างนี้ก็คุยกันผ่าน Social เพียงอย่างเดียว โดยสร้างกลุ่ม Line ขึ้นมา เพื่อนในทีมบางคนยังไม่เคยเห็นหน้ากันเลยด้วยซ้ำ จึงจำเป็นต้องให้มาพบหน้ากันสักครั้ง เพราะล้วนแต่ทำงานในบริษัทคนละแห่งกัน ก็เลยถือโอกาสช่วงเย็นหลังเลิกงาน นัดพบปะเจอหน้า

แน่นอนการแข่งขันย่อมมีกฏกติกา มาดูรายละเอียดกันหน่อย

กติกา
  • ทีมที่เข้าแข่งขันต้องมีสมาชิกตั้งแต่ 1 – 5 คน
  • เรามีเวลาให้ 48 ชั่วโมงสำหรับการสร้าง Web Application ห้ามสร้างก่อนเป็นอันขาด
  • ทุกทีม ต้อง push code ทั้งหมด ขึ้น GitHub อย่างสม่ำเสมอ ในช่วงเวลา 48 ชั่วโมง
  • งานของทุกทีมต้อง Host อยู่บน Firebase hosting เท่านั้น
  • เรามีกฏนิดหน่อยสำหรับ Web Application และทางกรรมการขออนุญาตตัดสิทธิสำหรับ Application ที่ทำผิดกฏ
  • ทางทีมผู้จัดงานจะส่งรายละเอียด เรื่องวิธีการส่ง Web application หลังจากที่ได้สมัครแล้ว

ดูรายละเอียดของกติกา ก็ไม่ได้มีอะไรที่มองดูแล้วว่าจะยาก เป็นห่วงเพียงเรื่องเดี่ยวคือ Firebase hosting ซึ่งในทีมก็ยังไม่เคยได้ลองใช้งานกันเลย

ต่อมาเรื่องกฏที่ต้องให้ความใส่ใจเป็นพิเศษ

กฏ
  • เราไม่อนุญาตให้ ทำ Backend หรือ API เองเป็นอันขาด
  • แต่มันจะไม่สนุกเลยถ้าใช้ API ไม่ได้เลย เราจึงยอมให้ใช้ API ที่เป็น Public และ “ฟรี” ได้ (API ที่เป็น Free plan นับเป็น ฟรีเหมือนกัน)
  • Frontend Library ต่าง ๆ ที่เปิดเป็น Public สามารถใช้งานได้ทั้งหมด
  • Web Application จะต้องมี Web App Manifest (สามารถ Add to home screen ได้สมบูรณ์) และ Service worker ติดตั้งอยู่
  • Web Application จะต้องใช้งานได้บางส่วนหากไม่ได้เชื่อมต่อ Internet

งานยากเลยสำหรับกฏบางข้อกับเวลา 48 ชม. ส่งรายละเอียดให้สมาชิกแบ่งงานกันไปคิด ทุกคนตั้งทำถาม “พวกเราจะทำเกี่ยวกับอะไรดี”

1 สัปดาห์ก่อนถึงวันแข่งขัน

นัดรวมตัวกันอีกครั้ง ครั้งนี้เป็นวันที่ต้องนำ Idea ของแต่ละคนมา Share กันแล้วว่าจะทำอะไรดีในช่วงระยะเวลาแข่งขันอันสั้นนี้ ได้ข้อสรุปว่าเราจะใช้ Web Navigator เป็นสิ่งหลัก โดย Interface Navigator นี้จะสามารถเรียก Device ของเครื่อง Client ที่ User ใช้งานอยู่นั้น โดยจะเรียก Feature ของ Hardware ได้หลายอย่างมาก เช่น Microphone , Camera ,Bluetooth ,Notification ,Audio ,Battery ,Geolocation เหล่านี้เป็นต้น จึงเลือกมาใช้เป็น Feature ของ Application ทีมเรา

จึงได้สรุป Feature หลัก ๆ ที่ตั้งใจว่าที่จะให้ Application เราต้องสามารถทำได้

  • Take photos ต้องถ่ายภาพได้
  • เก็บ Location (Latitude,Longitude) ของ User ที่ใช้งานได้
  • Google Map ต้องแสดงตำแหน่งของ User ที่ใช้งานได้บนแผนที่ พร้อมกับแสดงตำแหน่งของ User ที่เรียกใช้งาน App ได้ในบริเวณใกล้เคียง โดยแสดงเป็นตำแหน่ง Mark บน Google Map
  • แสดง Gallery รูปภาพของตัวเองได้
  • สามารถลงชื่อเข้าใช้งาน App ได้ด้วย Google Account , Facebook Account
  • แสดง Gallery รูปภาพของ User ที่ใช้งาน App โดยทำมาแสดงเป็น Feeds ข้อมูล โดยจะทำการกด Like ให้กับรูปนั้น ๆ ได้
  • มีการแจ้งเตือน User ให้กรณีที่มี User อื่นที่ถ่ายภาพในบริเวณใกล้เคียงได้
  • ส่ง Email แจ้งเตือน กรณีลงชื่อเข้าใช้งานในครั้งแรก

เมื่อสรุปขอบเขตของ Application ได้แล้วก็ลงมือ ออกแบบ Prototype หน้าจอก็ได้ออกมาหน้าตาแบบนี้

เนื่องจากเป็นการ Coding ข้ามวันข้ามคืนก็ต้องการสถานที่กบดานกัน ผมเลยเสนอสถาที่นี่เลย บ้านบางเขน ถ้าใครเคยได้ยินจะพอทราบว่าเป็นแหล่งพักผ่อนในแบบคนที่ชอบถ่ายภาพ และก็จะมี Zone ห้องแอร์สำหรับนั่งอ่านหนังสือ คุยงาน ถือว่าเหมาะมากสำหรับนั่งทำงานบรรยากาศเงียบสงบแอร์เย็น เพราะเสียค่าบัตรเข้าใช้บริการ 20 บาท (สามารถนำบัตรไปแลกน้ำเปล่าได้ 1 ขวด) ก็สามารถเข้าใช้บริการห้องอ่านหนังสือได้แล้ว พวกเราเลือกที่จะไปรวมตัวกันที่นี่

วันแข่งขัน

และแล้วก็มาถึงวันเริ่มแข่งขัน วันที่ 23 มิถุนายน 2560 20:00 น. ทีมเราลงความเห็นว่าจะผักผ่อนกันก่อนโดยจะไปเริ่ม เช้าวันเสาร์ 09:00 น.

เราแบ่งงานกันเป็นส่วน ๆ รับผิดชอบ เพราะด้วยการออกแบบแยกส่วนการทำงานแล้วจึงไม่ยากในการ Coding เท่าไหร่แต่ก็ติดปัญหาเป็นช่วง ๆ เพราะเป็นสิ่งที่ต้องเรียนรู้ใหม่เกือบทุกคน

โดยเราเลือกใช้ Angularjs และเลือก materializecss.com  นี้เป็นหลักในการ Implement App ในครั้งนี้

ในระหว่างที่แต่ละทีม Coding อยู่แต่ละทีมก็จะสามารถความเลื่อนไหวของทีมอื่น ๆ ได้แบบ Realtime เพราะทีมผู้จัดออกแบบการแสดงผลของคะแนนไว้แล้ว สามารถเข้าดูได้ตลอดเวลา

เกณฑ์การตัดสินมีคะแนนรวมของเครื่องมือที่ชื่อ Lighthouse  ที่จะค่อยวัดประสิทธิภาพแอพเราว่ามีคะแนนรวมเท่าไหร่โดยแบ่งการให้คะแนนออกเป็น 4 ด้าน

  • Progressive Web App
  • Performance
  • Accessibility
  • Best Practices

โดยทุกหัวข้อจะมีคะแนน 100 คะแนน ก็รวม ๆ แล้ว 400 คะแนนเห็นจะได้ซึ่งทีมเราก็ไม่น้อยหน้า ก็ต้องวัดประสิทธภาพด้วยเช่นกัน

ช่วงแรกเรามองคะแนนของให้ความสนใจกับเรื่อง Progressive Web App ซะส่วนใหญ่ และจะกลับมาปรับ Tune Performance ในภายหลังแต่ก็ไม่ทันเวลา แต่มองว่าเครื่องมือนี้ช่วยเราได้ในระดับนึง

เราใช้เวลาได้ไม่เต็มที่นั่งเพราะก็มองการแข่งครั้งนี้เป็นการเก็บประสบการณ์ไปก่อน ต้องขอบคุณทุกคนในทีมที่ช่วยกันได้อย่างเต็มที่

นี่คือตัวอย่างหน้าจอสุดท้ายก่อนหมดเวลา

 

สรุปสิ่งที่ได้รับจากงาน Cloud Functions for Firebase and Next Generation of Web

Cloud Functions for Firebase

ถือเป็นครั้งแรกที่บริษัท Tencent จัดงาน Tencent Open House #1 ซึ่งบริษัท Tencent ฟังดูอาจจะไม่คุ้นหูเพราะ Tencent ถือบริษัทที่ถือกำเนิดที่ประเทศจีนเป็นบริษัทยักษ์ใหญ่ทางด้านวงการไอที แบบเดียวกับ Alibaba และ Baidu เลยที่เดียว

Tencent เป็นบริษัทให้บริการด้าน System Integration หรือบริการวางระบบคอมพิวเตอร์และเครือข่ายสำหรับองค์กรเป็นหลักถ้า Product ที่ดัง ๆ ในไทยบ้านเราก็ยกตัวอย่างเช่น sanook.com , Wechat , Joox , ฯลฯ เป็นต้น ข้อมูลเพิ่มเติมเกี่ยวกับบริษัท Tencent

งานถูกจัดขึ้นในช่วงเย็นของวันที่  25 เมษายน 2017 เวลา 18.00-21.00 ที่ บริษัท เทนเซ็นต์ (ประเทศไทย) อาคารเมืองไทย-ภัทร คอมเพล็กซ์ (อาคาร A) ชั้น 16

Agenda ของงาน
18.00 – 18.45 | Register, discussion and networking with free pizza and drinks
18.45 – 19.00 | Opening Notes by Tencent Thailand
19.00 – 19.45 | “Topic : Cloud Functions for Firebase” by K.Tee
19.45 – 20.00 | Break
20.00 – 20.45 | “Topic : Next Generation of Web” by K.Thang
20.45 – 21.15 | Q&A, Networking, Chit-Chat

ใช้เวลาเดินทางไม่นานเมื่อถึงที่จัดงาน เดินเข้าไปก็จะพบกับอาหารที่ทางผู้จัดงานมีให้กินก่อนเข้าฟังการบรรยาย

ส่วนด้านหน้าเวทีการบรรยาย

เมื่อได้เวลาตาม Agenda ที่วางไว้ท่านแรกคุณตี๋ (จิรวัฒน์ กรัณย์วิทยาการ) Google Developer Expert ด้าน Firebase คนแรกของประเทศไทย โปรไฟล์ไม่ธรรมดาครับคนนี้มาพูดเสนอกับ Product ที่เพิ่งจะเปิดตัวใหม่ของ Firebase ที่ชื่อ Cloud Functions for Firebase

Cloud Functions จะมาช่วยแก้ปัญหาให้ Developer เข้าถึง Event ต่าง ๆ ของ Firebase ได้เป็นการรวมการทำงานของ Firebase กับ Google Cloud เข้าด้วยกัน สิ่งที่ CloudFunctions นี้จะช่วยให้ช่วยให้ผู้ใช้งานทราบและพร้อมกับทำการปรับปรุงข้อมูลบน Database ได้เลยโดยผ่าน Logic การทำงานที่เราได้ทำการเขียนฝั่งไว้ที่ Cloud Functions นั้นแล้ว

โดยแต่ก่อนการที่จะใช้งาน Firebase จะยังไม่สามารถเขียน Functions การทำงานในฝั่งของ Firebase ได้จะเป็นต้องเขียน Function การทำงานในฝั่ง Server ของเราเองและค่อยเรียกใช้ Firebase Database ถ้าอยากจะใช้งานเกี่ยวกับการเก็บข้อมูลสิ่งเหล่านี้จะถูกทำที่ฝั่ง Server เราเอง  แต่เมื่อมี Firebase Cloud Functions มาจะช่วยให้เราสามารถเขียน Functions การทำงานใน Firebase ได้เลย ยกตัวอย่างเช่น

ตัวอย่างการทำงานของ Cloud Functions for Firebase

เมื่อมีการส่ง message เข้ามาให้ฝั่ง Firebase Server และ Cloud Functions จะดักจับ Event Functions ที่เราเขียนไปเพื่อที่จะสั่งให้ไปทำอะไร โดย Function นี้จะทำงานอยู่เบื้องหลังโดยไม่ต้องมาเขียน Function จัดการในฝั่ง Server ของเราเองเลย

อีก 1 ตัวอย่างการทำงาน

เมื่อมีการสั่งอัพโหลดไฟล์เข้ามาที่ Firebase Storage จะทำการ Trigger ไปบอก Cloud Function ให้ทำการ Resize Picture และเก็บใน Firebase Storage โดยเพื่อที่จะใช้ในการ preview Picture บน Mobile จะไม่ต้องทำเป็นต้องแสดงรูปที่มีขนาดใหญ่ โดยตัว Function  Resize Picture จะถูกเขียนฝั่งไว้ที่ Cloud Functions เรียบร้อยแล้วเพียงแค่เราเรียก Service การอัพโหลดรูปจาก Firebase Cloud Functions เท่านั้นเอง

การที่จะเริ่มใช้งาน Firebase Cloud Functions

Cloud Functions for Firebase ณ เวอร์ชั่นตอนนี้ Support ภาษา Javascript ได้ภาษาเดียวเท่านั้นโดยเครื่อง developer จำเป็นต้องติดตั้ง NodeJS และ Firebase CLI ตัวอย่างการเริ่มต้นใช้งาน Cloud Functions Get Start ทุกครั้งที่ developer ได้ทำการสร้าง Functions เสร็จ ทุกครั้งจำเป็นจะต้อง deploy functions เหล่านั้นที่ได้พัฒนาไปที่ Firebase ก่อนทุกครั้งโดยจะเสียเวลาประมาณ 1-3 นาที

จบไปกับการบรรยายเรื่อง Cloud Functions for Firebase

พักเบรคกันสักครู่ ต่อกันด้วยเรื่องที่ถูกใจนักพัฒนาสาย web กันหน่อย

Next Generation of Web

บรรยายโดยคุณตั้ง (วรัทธน์ วงศ์มณีกิจ) Google Developer Expert ด้าน Web Technologies สายโหดด้านเว็บมาอัพเดทแนวทางการพัฒนาเว็บในปัจจุบันและต่อไปในอนาคต

เนื่องจากสายเว็บจะอยู่ไปต่อให้ได้ต้องทำงานให้เสมือนเป็น app บน mobile แอพนึง application ที่พัฒนาสำหรับ mobile platform เพราะด้วยขนาดที่ใหญ่เปลืองพื้นที่จัดเก็บและบางแอพยังไม่คุ้มค่ากับการ Download เพื่อมาติดตั้งเพียงแค่ใช้งานเพียงน้อยนิด จึงทำให้ผู้ใช้งานเลือกที่จะลังเลกับการ Download เพื่อมาติดตั้งใช้งานบนเครื่อง การพัฒนา Website ให้มีหน้าตาคล้ายกับ Mobile App จึงมาช่วยตอบโจทย์เรื่องขนาดของ Application นี้ได้

เรื่องการทำเว็บ Responsive ที่ว่าเป็นเรื่องที่ได้รับความนิยมมากในไทย แต่ผิดกับต่างประเทศที่มองว่าเรื่องการพัฒนาเว็บแบบ Responsive นี้มองว่าไม่จำเป็นที่จะพัฒนาเพื่อในเว็บของเรานั้นเป็น Responsive เลย เพราะด้วยว่าผู้ใช้งานบน Mobile ก็ไม่ได้ยืดขยายเว็บ จึงมองว่าไม่จำเป็น ขนาดยักษ์ใหญ่อย่าง Facebook ยังแยกการพัฒนาเว็บให้ Run ได้เฉพาะ platform เดียวเท่านั้น

https://m.facebook.com/ ที่พัฒนามาเพื่อ run บน mobile เพียงอย่างเดียว

โดยคุณตั้ง มอง 7 สิ่งนี้ที่จำเป็นสำหรับการพัฒนาเว็บในอนาคตไว้ดังนี้

  • More Look Like App : การที่จะพัฒนาเว็บให้เรียนแบบ mobile application นั้นได้เว็บเราจพเป็นต้องรองรับการทำงานแบบ PWA (Progressive Wep App)
  • More Speeds : ในปัจจุบันเรื่อง Speeds สำหรับผู้ใช้งานคือว่าสำคัญมากเมื่อ 2015 โดยเฉลี่ย 53% สำหรับ User จะไม่รอ Website ที่โหลดหน้าแรกยาวนานเกินกว่า 3 วินาที และต่อไปในปี 2016 เปอร์เซ็นการที่ User จะไม่รอ Website ที่โหลดนาน ๆ ก็จะเพิ่มสูงขึ้นเรื่อย ๆ
  • More User Engagement : การที่เว็บจะทำงานให้คล้ายกับ Mobile App ได้แบบเนียนมาก ๆ เรื่องที่แอพทำได้ Notification ก็ควรที่จะทำได้ซึ่งในปัจจุบัน Browser บางตัวสามารถทำงานได้แล้ว
  • More Hardware Access : เว็บเองสามารถเรียกใช้งาน Hardware บน Device ได้แล้ว เช่น Microphone , Camera ,Bluetooth เป็นต้น ยิ่งเข้าไกล้ mobile app เข้าไปทุกที
  • More Connectivity independent : สิ่งหนึ่งที่แอพ บน Mobile บางแอพทำงานได้ในสถานะที่ไม่มี internet ที่ฝั่งเว็บยังไม่สามารถทำได้ในอดีตซึ่งมองว่าเรื่องนี้เป็นสิ่งที่ต้องได้รับการแก้ไข ปัจจุบันสิ่งนี้ได้รับการแก้ไขแล้วด้วย Services Worker ทำให้ Website ทำงานได้แบบสถานะ Offline Browser จ้าวดัง ๆ ในตอนนี้ก็ Support เรื่องนี้เรียบร้อยแล้ว
  • More Secure : เพราะว่าเรื่องความปลอดภัยในปัจจุบันกำลังให้ความสำคัญเป็นอันดับต้น ๆ การที่ User จะมั่นใจได้ว่า Website ที่เข้าใช้งานนั้นมีความปลอดภัยในระดับนึง ซึ่งการทำ Https ให้กับ Website จึงเป็นสิ่งที่ทำให้ User มั่นใจในระดับนึงได้ว่าเว็บไซตที่กำลังเข้านั้นมีความปลอดภัย Top 100 Website ในไทย มีเว็บที่เป็น Https เพียง 40 Website แต่ที่น่าตกใจมีเพียงไม่ถึง 10 % เป็น Https แบบสมบูรณ์ 100 %
  • More Easier : ความง่ายในการใช้งานถือเป็นส่วนสำคัญที่ทำให้ Website จะต้องตระหนักถึงการพัฒนาเว็บไซต์ให้ง่ายต่อการใช้งาน Google มองเห็นเรื่องการทำระบบ Login เป็นเรื่องที่ทำบ่อยจึงกำเนิด Feature Auto Login ให้สำหรับการจำข้อมูลการ Login ของ User กับ Website นั้น ๆ และการใช้งานบน Device อื่นนอกเหนือจากที่เคย Login ไว้ในการเข้าใช้งาน Website เดียวกันจะแจ้งการ Login เคยเข้าใช้งาน Website นี้จาก User นี้จะให้ทำการ Login ด้วย User นี้เลยหรือไม่ เรื่องนี้ก็เลยทำให้การใช้งาน Website ดูง่ายขึ้นไปอีก

 

เริ่มต้นใช้งาน Esp8266 เปิด-ปิด LED กับ Netpie Cloud Platform Services

เมื่อครั้งงาน Arduino Day 2017 (Bangkok) ที่ผ่านได้ยินทาง Nectec- Thialand ได้มาเชิญชวนให้ใช้ Product ที่พัฒนาโดยคนไทยทางด้าน Cloud Platform Service ที่ชื่อว่า NetPie เขาบอกว่า Product นี้ช่วยให้การพัฒนางานด้าย IOT สะดวกและรวดเร็วยิ่งขึ้น

Netpie Features

  • THING-CENTRIC DEVELOPMENT  เป็นเสมือนศุนย์กลางเพื่อใช้ในการรับส่งข้อมูลกัน
  • IDENTITY MANAGEMENT สามารถเข้าถึง Netpie โดยไม่จำเป็นว่า Client จะมี IP หรือไม่มีก็ได้
  • DYNAMIC AUTHORIZATION สามารถปรับเปลี่ยนการเข้าถึงข้อมูลแบบไดนามิก
  • TRANSPARENT CONNECTIVITY การติดต่อสื่อสากันระหว่าอุปกรณ์สามารถทำได้เสมือนความรู้สึกแบบ end-to-end
  • SERVICE-ORIENTED MODEL หากต้องการความช่วยเหลือให้นุกถึง Netpie
  • TRUE CLOUD ARCHITECTURE มีการออกแบบมาเพื่อให้บริการแบบ Cloud เพื่อให้สามารถขยายขนาดได้ในอนาคต

อ่านข้อมูลเพิ่มเติมได้ที่ https://www.nectec.or.th/innovation/innovation-software/netpie.html

เริ่มต้นการใช้งาน Netpie กับ Esp8266

เตรียมเครื่องมือกันก่อน

  1. Download Arduino IDE 1.6.9 or later from https://www.arduino.cc/en/Main/Software
  2. หลังจากติดตั้งสำเร็จ, open Preferences
  3. เพิ่ม “http://arduino.esp8266.com/stable/package_esp8266com_index.json" ใส่ในช่อง “Additional Board Manager URLs” กดOK
  4. เปิดเข้าเมนู Boards Manager  ค้นหา “esp8266” และติดตั้ง
  5. ในเมนู Tools เลือก ESP8266 boards
  6. Download Microgear library จาก https://github.com/netpieio/microgear-esp8266-arduino/archive/master.zip
  7. เลือกเมนู Sketch => Include Library => Add .zip Library เลือก microgear.zip ที่ Download มาจากข้อ 6.

เมื่อติดตั้งเครื่องมือพร้อมสิ่งที่ต้องทำต่อไปมีด้วยกัน 2 สิ่ง

  1. ไปสร้าง Project ที่ https://netpie.io/ (ลงทะเบียนฟรี) สมัครสมาชิก เข้าใช้งานระบบ และก็ให้ทำตามขั้นตอนการสร้าง Project จากนี้ https://netpie.io/getstarted
  2. เขียนโค๊ด
    /*  NETPIE ESP8266 basic sample                            */
    /*  More information visit : https://netpie.io             */
    
    #include <ESP8266WiFi.h>
    #include <MicroGear.h>
    
    const char* ssid     = <WIFI_SSID>;
    const char* password = <FILE_PASSWORD>;
    
    #define APPID   <APP_ID>;  //====ได้จากตอนที่เราตั้งชื่อ Project ที่ netpie
    #define KEY     <KEY>;  //====จะได้จากตอนสร้าง Key
    #define SECRET  <SECRET>; 
    #define ALIAS   "led1";
    
    WiFiClient client;
    
    int timer = 0;
    int i = 1;
    MicroGear microgear(client);
    
    int LED = D4;
    
    /* If a new message arrives, do this */
    void onMsghandler(char *topic, uint8_t* msg, unsigned int msglen) {
      Serial.print("Incoming message --> ");
      msg[msglen] = '\0';
    
      char strState[msglen];
      for (int i = 0; i < msglen; i++)
      {
        strState[i] = (char)msg[i];
        Serial.print((char)msg[i]);
      }
    
      Serial.println();
    
      String stateStr = String(strState).substring(0, msglen);
    
      //=========== ช่วงประมวลผลคำสั่ง =============
      Serial.println("stateStr ::== ");
      Serial.println(stateStr);
      
      if (stateStr == "ON"){
        digitalWrite(LED, HIGH);
        microgear.chat("sw1", "ON");        //==== คำสั่ง chat เพื่อบอกส่งค่าสถานะไปยังหลอด LED บน NETPIE Freeboard
      }else{
        digitalWrite(LED, LOW);
        microgear.chat("sw1", "OFF");       //==== คำสั่ง chat เพื่อบอกส่งค่าสถานะไปยังหลอด LED บน NETPIE Freeboard
      }
    
      //=========== ช่วงประมวลผลคำสั่ง  =============
    }
    
    void onFoundgear(char *attribute, uint8_t* msg, unsigned int msglen) {
      Serial.print("Found new member --> ");
      for (int i = 0; i < msglen; i++)
        Serial.print((char)msg[i]);
    
      Serial.println();
    }
    
    void onLostgear(char *attribute, uint8_t* msg, unsigned int msglen) {
      Serial.print("Lost member --> ");
      for (int i = 0; i < msglen; i++)
        Serial.print((char)msg[i]);
      Serial.println();
    }
    
    /* When a microgear is connected, do this */
    void onConnected(char *attribute, uint8_t* msg, unsigned int msglen) {
      Serial.println("Connected to NETPIE...");
      /* Set the alias of this microgear ALIAS */
      microgear.setAlias(ALIAS);
    }
    
    
    void setup() {
      /* Add Event listeners */
    
      /* Call onMsghandler() when new message arraives */
      microgear.on(MESSAGE, onMsghandler);
    
      /* Call onFoundgear() when new gear appear */
      microgear.on(PRESENT, onFoundgear);
    
      /* Call onLostgear() when some gear goes offline */
      microgear.on(ABSENT, onLostgear);
    
      /* Call onConnected() when NETPIE connection is established */
      microgear.on(CONNECTED, onConnected);
    
    
      Serial.begin(115200);
      Serial.println("Starting...");
    
      /* Initial WIFI, this is just a basic method to configure WIFI on ESP8266.                       */
      /* You may want to use other method that is more complicated, but provide better user experience */
      if (WiFi.begin(ssid, password)) {
        while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print(".");
        }
      }
    
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    
      /* Initial with KEY, SECRET and also set the ALIAS here */
      microgear.init(KEY, SECRET, ALIAS);
    
      /* connect to NETPIE to a specific APPID */
      microgear.connect(APPID);
      pinMode(LED, OUTPUT);
    }
    
    void loop() {
    
      /* To check if the microgear is still connected */
      if (microgear.connected()) {
        Serial.println("connected");
    
        /* Call this method regularly otherwise the connection may be lost */
        microgear.loop();
    
    
      }
      else {
        Serial.println("connection lost, reconnect...");
        if (timer >= 5000) {
          microgear.connect(APPID);
          timer = 0;
        }
        else timer += 100;
      }
      delay(100);
    }

    ส่วนการต่อ LED ให้ไปดูต่อบทความ https://www.poolsawat.com/no-off-led-with-nodemcu/

เมื่อดำเนินการขั้นตอนที่กล่าวมาเสร็จก็ลองทดสอบ

หลักการทำงานของ Netpie กับ ESP8266

  • Run Program บน NodeMCU ต่อ LED ไว้
  • จะสั่งการทำงานจากหน้า Freeboard Dashboard ที่ Netpie มีบริการไว้ให้
  • กดปุ่มปิด ไฟจะติด กดปิดไฟจะดับ
  • ถ้าการทำงานไม่เป็นไปตามนี้ ให้ไปตรวจสอบ ค่าที่ #defind appid,key,secret อีกครั้ง

 

Electron Framework เริ่มต้นการสร้างโปรเจค Hello World

บทความนี้จะพามาทำ Desktop App ด้วย Javascript , HTML คุณฟังไม่ผิดหรอก Javascript สามารถใช้พัฒนาได้จริง ๆ

การที่เราจะพัฒนา App ที่ Run ได้บน Desktop นั้นคงจะจินตณาการไปว่าต้องเขียนด้วย C/C++, VB, .NET, Java หรือ Objective-C/Swift ได้เท่านั้น แต่สำหรับยุคปัจจุบันเทคโนโลยีบนโลกเปลี่ยนไปไวมาก Web Application ที่ถือว่าได้รับความนิยมมากในปัจจุบันก็ยังคงหนีไม่พ้นการนำ Javascript เข้ามาช่วยเพิ่มขีดความสามารถของ Application นั้นให้ทำงานได้อย่างมีประสิทธิภาพ Javascript ที่ต้องบอกว่าความสามารถครอบจักรวาลจริง ๆ จึงมีคนคิดค้นให้ Javascript Language นี้สามารถนำมาใช้พัฒนา Desktop Application ได้อย่างไม่น่าเชื่อ




เครื่องมือยอดฮิตในปัจจุบันอย่าง Atom Editor ,VSCode Editor นั้นก็ถูกพัฒนามาจาก Electron Framework ด้วยกันทั้งนั้น

เริ่มต้นการเขียนโปรแกรมเพื่อให้แสดง Hello World

เพราะด้วยว่า การติดตั้ง Electron นั้นจำต้องทำผ่านทาง npm ของ NodeJS จึงอยากให้ติดตั้ง NodeJS ที่เครื่องคอมพิวเตอร์กันก่อนให้เรียบร้อย

หลังจากที่ได้ติดตั้ง NodeJS เป็นที่เรียบร้อยแล้วให้ทำการ install Package Electron แบบ Global ในเครื่องของเราด้วยคำสั่ง

npm install -g electron -prebuilt

รอจนกว่าจะติดตั้งเสร็จ (อาจจะใช้เวลานานสักหน่อย)

หลังจากติดตั้งสำเร็จให้ตรวจสอบ Electron Version เพื่อเช็คว่าติดตั้งเรียบร้อยดี ไม่มีปัญหา

electron --version

ต่อไปจะมาทำการสร้าง App Hello World กัน

สร้าง Directory ชื่อ App มาก่อนเพื่อเก็บโค๊ดของเราจากนั้นสร้างไฟล์ index.html ,main.js ขึ้นมา พร้อมใส่โค๊ดไปตามนี้

ไฟล์ index.html

<!DOCTYPE>
<html>

<head>
    <meta charset="utf-8">
    <title>App Electron By Poolsawat</title>
</head>

<body>
    <h1>Hello World</h1>
</body>

</html>




ไฟล์ main.js

const { app, BrowserWindow } = require('electron')
const url = require('url')
const path = require('path')

let win

app.on('ready', function() {
    win = new BrowserWindow({ width: 800, height: 600 })
    win.loadURL(url.format({
        pathname: path.join(__dirname, 'index.html'),
        protocol: 'file',
        slashes: true
    }))
})

ต่อไปทำการสั่งให้ Application Hello World ทำงานได้โดยการ Run ผ่าน Electron Command

electron main.js

สั่งงานเปิด-ปิดไฟ ด้วย Board ESP8266 NodeMCU v.3

สั่งงานเปิด-ปิดไฟ ด้วย Board ESP8266 NodeMCU v.3

กระแส IOT มาแรงมาก ได้ยินแบบนี้ก็ต้องเริ่มมองหาอุปกรณ์มาเล่นบ้าง

สำหรับมือใหม่ก็ต้องมองหาชุดอุปกรณ์ง่าย ๆ ราคาถูกมาลองเล่นกันก่อน

ผมเองก็เป็นมือใหม่ในเรื่องนี้ เริ่มต้นก็ต้องศึกษาหาข้อมูลก่อนไปเจอ ESP8266 NodeMCU

คิดว่ามัน่าจะดี ข้อดีของบอร์ดนี้คือ มี WIFI ในตัว

อุปกรณ์ที่ต้องเตรียม

  • NodeMCU (ตามตัวอย่างนี้จะใช้ Version 3)
  • สายไฟ จัมเปอร์ Jumper Wire M-F 20 cm 2 เส้น
  • Breadboard 840 holes
  • หลอด LED
  • สาย USB 2.0
  • Computer ที่ติดตั้งโปรแกรม Arduino IDE เรียบร้อยแล้ว (Download ได้ที่นี่)
    1. ขั้นแรกเปิด arduino IDE ขึ้นมาไปที่เมนู File -> Preferrence
    2. ช่องให้ใส่ “http://arduino.esp8266.com/stable/package_esp8266com_index.json” เข้าไปกด OK
    3. ไปที่เมนู Tools > Board > Boards Manager…
      1. พิมพ์คำว่า 8266 แล้วกด Install รอจนกว่าจะเสร็จ
      2. ติดตั้งเสร็จตรวจสอบ Boards ESP8266 ว่าจะแสดงดังภาพ
        •  
    4. เริ่มการเขียนโปรแกรมควลคุมให้ไฟ เปิด ปิด เบื้องต้น lab นี้ตัว arduino ide จะมีเตรียมไว้ให้แล้วให้เราเลือก File > Example > Basic > Blink
      •  
      • int led = D4;
        void setup() {
          pinMode(led, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
        }
        
        // the loop function runs over and over again forever
        void loop() {
          digitalWrite(led, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                            // but actually the LED is on; this is because 
                                            // it is acive low on the ESP-01)
          delay(1000);                      // Wait for a second
          digitalWrite(led, HIGH);  // Turn the LED off by making the voltage HIGH
          delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
        }
    5. ต่อสาย USB เชื่อม Computer กับ Board NodeMCU เพื่อทำการ Upload Program ที่ Complie สำเร็จ เข้าไปที่ Board NodeMCU
    6. ผลการทำงาน

แบ่งปันเรื่องราวการเข้าร่วมงาน CodeEXP งานของผู้ที่ผ่านการได้เข้าทำงานกับบริษัท Top Tech Company

Code EXP แชร์ประสบการณ์การเตรียมตัวและสัมภาษณ์งานกับ Top Tech Company

งานแบ่งปันประสบกานณ์จากผู้ที่ได้ผ่านด่านการสอบสัมภาษณ์งานบริษัทชั้นนำด้าน Technology ชั้นนำของโลก มาบอกเล่าแนวทางวิธีการก่อนการเริ่มสมัครงานกับบริษัทต่างชาติเหล่านี้ได้อย่างไร

แนวทางแรก ประเภทของวีซ่า

การเข้าไปทำงานที่ USA นั้นยากมาก โดยทาง USA ได้มีแบ่งคุณสมบัติของวีซ่าแต่ละประเภท ไว้ดังนี้

  • H-1B คือ หากท่านเดินทางไปยังสหรัฐอเมริกาเพื่อทำงานจำเป็นต้องมีวุฒิการศึกษาขั้น ต่ำปริญญาตรี และศึกษาในสาขาวิชาที่ตรงกับตำแหน่งที่ถูกว่าจ้าง
  • F-1 นักเรียนนักศึกษาที่เข้ามาเพื่อเรียนต่อในระดับปริญญาและสำเร็จการศึกษาจะได้โควต้าทำงานในประเทศ 1 ปีทันที
  • L-1 พนักงานที่ย้ายไปทำงานที่สหรัฐชั่วคราวภายใต้การจ้างงานของบริษัทที่อยู่ในเครือเดียวกัน
  • E-1/E-2 นักลงทุนเข้ามาลงทุน ( 1 ล้านเหรียญ )

แนวทาง 2 การยื่นใบสมัครผ่านเว็บไซต์

หลังจากได้ยื่นเมลล์หรือยื่นการส่งไปสมัครไปตามบริษัทต่าง ๆ เราจะรู้ได้อย่างไรว่าจะได้รับการพิรณาจากบริษัทนั้นหรือไม่โดยเบื้องต้นให้สังเกตุจากเมลล์ตอบกลับโดยสามารถจัดประเภทเมลล์เหล่านั้นได้ดังนี้

  • เมลล์ประเภทว่าส่งไปแล้วหายสาปสูญไปเลย
  • ตอบแบบปฏิเสธ
  • ประเภทแบบเชิญเข้าร่วมทำแบบทดสอบต่าง ๆ เพื่อเป็นด้านการทดสอบ

แนวทาง 3 แนะนำวิธีการไปศึกษาต่อต่างประเทศเพราะหลังจากเรียนจบ จะได้โควต้าอยู่ใน USA ต่ออีก 1 ปี

แนวทาง 4 ให้เพื่อนที่ทำงานในบริษัทแนะนำจะทำให้ทางบริษัทสนใจข้อมูลเราเป็นลำดับต้น ๆ แต่ก็ไม่ได้การันตีนะว่าจะได้กันทุกคน ฮาๆ ๆ

แนวทาง 5 เข้าร่วมการแข่งขันเพื่อเก็บประสบกาณ์ เช่น CodeJam , Facebook Hacker , Hackathon เป็นต้น

แนวทาง 6 การเข้าร่วม Contribute Open Source เข้าร่วมพัฒนา Project ตาม Github

แนวทาง 7 ให้ความสำคัญเรื่องเวลา เพราะการเข้าไปทำงานใน USA มีช่วงระยะเวลาจำกัด จึงให้คอยติดตามข่าวสารอยู่ตลอดเวลา

และเมื่อผ่านด่านการยื่นไปสมัครไปแล้ว ก็ต้องไปสู่ด่านการทดสอบต่อไป

  1. ผ่าน Recruiter
  2. Online Coding
  3. Online Coding อีกรอบ
  4. Networking
  5. Online Business
  6. Online Interview

อื่น ๆ ที่เกี่ยวข้องกับการเตรียมพร้อมเพื่อเข้าสมัครงาน

  • ภาษาอังกฤษ (สำคัญ) ของมันแน่อยู่แล้ว
  • Data Structure And Algorithm
    • Recusion
    • String
    • Time/Speed (Big O)
    • Array
    • Bit Maniputation
    • HashMap
    • Stack
    • Heap
    • DFS / BFS
    • Graph
    • Sorting
    • Insert Sort
    • Merge Sort
    • Searching
    • Binary Search
    • ฯลฯ
  • Sport programming
  • Code Forces
  • KackerLengh.com , Leetcode.com

ทิ้งท้าย 5 Key ที่จะทำให้เราประสบความสำเร็จ

  1. ตั้งเป้าหมายของเราไว้สูงเสมอ ยิ่งสูงยิ่งดี
  2. ไม่มีอะไรแก่เกินเรียน
  3. มีใจรักในสิ่งที่ทำ
  4. ซ้อม ๆ ๆ
  5. อย่ายอมแพ้

 

 

 

 

Docker ฉบับผู้เริ่มต้น (Setup On Window)

Docker คืออะไร

Docker คือ Platform สำหรับการ Developing, Shipping and Running Application ที่สร้างสภาพแวดล้อมเสมือนจริง

Docker Platform มีส่วนประกอบด้วยสิ่งเหล่านี้

Docker Engine คือ  เป็นเหมือนตัว Runtime สำหรับ Build และ Run Docker Container ช่วยให้คุณสามารถจัดการ Dependencies ต่าง ๆ

Docker Hub คือ แหล่งที่จัดเก็บ Docker Image ต่าง ๆ (มองว่าคล้ายกับ github)

Docker Machine คือ สำหรับการ Deploy Docker ไปที่ Production

Docker Swarm คือ เครื่องมือที่จัดการเครื่องที่ Run Docker หลาย ๆ เครื่องให้อยู่ในสภาพแวดล้อมเดียว สามารถ scale ระบบบน Docker Swarm ได้มีประสิทธิภาพมากกว่าการสั่งงาน Docker ทีละเครื่อง

Docker Compose คือ การร่วมเอา Docker Container หลายๆ Container มาสั่งให้ทำงานพร้อมกัน

Kitematic คือ เครื่องมือ GUI ที่รวบรวมคำสั่งของ Docker Command ต่าง ๆ ในรูปแบบ UI ให้สามารถใช้งานได้ง่าย ๆ ยิ่งขึ้น

ปัญหาที่เหล่า Developer พบเจอในการ Development Application

  • เสียเวลาติดตั้ง Application ใหม่ทุกครั้ง
  • Run Application บน Production ไม่ได้แต่ Run บนเครื่อง Dev ได้ (เป็นแบบนี้บ่อยมาก)
  • มี Dev เข้ามาเพิ่มในทีมต้องเสียเวลาในการจัดเตรียม Environment ใหม่ (ซึ่งเตรียมแล้วอาจจะเกิดปัญหา Environment ไม่ตรงกับเครื่องเพื่อนในเรื่องของ Version ต่างๆ)

Install Docker On Window Side

  1. ตรวจสอบสภาพความพร้อมของเครื่องที่จะทำการ install
    1. ตรวจสอบ OS Version ของเครื่องที่จะ Install
    2. ตรวจสอบ Virtualization ว่า enabled อยู่หรือไม่ ให้ทำการ enabled Virtualization ก่อน
  2. Install Tools
    1. Install Docker Toolbox  (Click next, next, …)
    2. Install VirtualBox
  3.  ตรวจสอบ Icon Tools บนหน้า Desktop ของเครื่อง Computer คุณ

docker-icon

เริ่มการเข้าใช้งาน Docker

  1. Click Icon Docker Quickstart ขึ้นมา
  2. ตรวจสอบ Docker-machine IP
  3. ตรวจสอบ Version
    docker --version
    
    docker-compose --version
    
    docker-machine --version

ทำความเข้าใจ Docker Containers และ Docker Images

  • Images
    • เมื่อเป็น Image แล้วจะอ่านได้อย่างเดี่ยวแก้ไขอะไรไม่ได้
    • ถูกสร้างขึ้นจากผู้ใช้งาน Docker
    • ถูกจัดเก็บไว้ที่ Docker Hub หรือ Local Registry
  • Containers
    • แยกการทำงานออกจากกัน
    • Containers ต่าง ๆ จำเป็นต้อง Run บน Application ของคุณ
    • 1 Container จำเป็นต้องมี Image 1 อันเป็นอย่างน้อย




Create Hello World Container

#Syntax
docker run [options] [image] [command] [args]

#examples
docker run ubuntu:14.04 echo "Hello World"

#*image is specified with repository:tag

Docker Command อื่น ๆ ที่ใช้งานบ่อย ๆ

#Find Images
docker images

#Find Container is Running
docker ps
# Find Container all
docker ps -a

#Find Logs is Container
docker logs <container id>

#Container with Terminal
# -i flag tells docker to connect to STDIN on the container
# -t flag specifies to get a pseudo-terminal
docker run -i -t ubuntu:latest /bin/bash

#Running in Detached Mode (Run Background Process)
docker run -d <image id>

#More Practical Container
# -P flag to map container ports to host ports
docker run -d -P tomcat:7


#start container
docker start <container id>

#stop container 
docker stop <container id>

#delete conatiner
docker rm <container id>

#delete image
docker rmi <image id>
#or
docker rmi <repo:tag>

#mapped to a host directory
docker run -i -t -v /data/src:/test/src nginx:1.7

#mapping ports
docker run -d -p 8080:80 nginx:1.7

#automaping ports
docker run -d -P nginx:1.7

#creating a Link
docker run -d -P --name website --link database:db nginx

สรุปสิ่งที่ได้รับจากงาน OpenStack Thailand Chapter – User and Contributor MeetUp #1

OpenStack Thailand Chapter – User and Contributor MeetUp #1 30 พฤศจิกายน 2016 เวลา 18:00 – 21:00

Agenda :

18:00 – 18:30 น.  ลงทะเบียน
18:30 – 19:00 น.  กล่าวต้อนรับ และ วัตถุประสงค์ในการจัดตั้งกลุ่ม OpenStack Thailand Chapter – User and Contributor
19:00 – 19:30 น.  Why you need to attend Openstack Summit and how to attend at very affordable budget? โดย Dr. Abhisak Chulya, CEO and Founder, NIPA.cloud
19:30 – 19:45 น.  พักการบรรยาย
19:45 – 20:30 น. How to be OpenStack Contributor โดย คุณจิรายุส นิ่มแสง, CEO and Founder, Opsta
20:30 – 21:00 น. Open Discussion

OpenStack คืออะไร

OpenStack การรวมกันของ Projects Open Source เพื่อให้เกิดเป็น Project Openstack นี้ขึ้นมา สำหรับใช้เพื่อการสร้าง Private หรือ Public Clounds

openstack-software-diagram

โดย OpenStack Project นี้เองก็จะมี Project ที่เป็น Core Services หลักอยู่ ประกอบด้วยกันอยู่ 6 Services

  • NOVA คือ เป็นตัวแทนของ Service ที่จัดการ Compute
  • NEUTRON คือ Service จัดการระบบ Networking
  • SWIFT คือ Service ที่เอาไว้จัดการ Object Storage สำหรับจัดเก็บข้อมูลแบบ cloud storage จัดเก็บข้อมูลและเรียกใช้งาน แบบ API
  • CINDER คือ  Block Storage
  • KEYSTONE คือ Service ตรวจสอบและอนุมัติการให้บริการสำหรับบริการ OpenStack ทั้งหมดในระบบ
  • GLANCE คือ Service จัดการเกี่ยวกับการให้บริการเกี่ยวกับ Media ต่าง ๆ

 

openstack-core-service

และ Optional Service โดยให้พิจรณาจาก Maturity ว่ายิ่งเยอะ ยิ่งดูเสถียรเหมาะแก่การจะทำไปใช้งาน

openstack-optional-serviceOpenstack ประกอบด้วย 4 “Open” เข้าด้วยกัน

  • Open Source
  • Open Design
  • Open Development
  • Open Community

OpenStack จะถูกเรียกแต่ละ version release ตามครั้งการจัดรวม Community

  • Barcelona (OCATA) Fall 2016
  • Austin(NEWTON) Spring 2016
  • Tokyo(MIKATA) Fall 2015
  • Vancouver(LIBERTY) Spring 2015
  • Paris(KILO) Fall 2014
  • Atlanta(JUNO) Spring 2014
  • Hong Kong(ICEHOUSE) Fall 2013

ซึ่ง Release Mitaka (2016-04-07) ถูกบันทึกสถิติไว้

  • ผู้เข้าร่วมงาน 40,497 คน
  • บริษัทที่คอยสนับสนุนกว่า 596 บริษัท
  • 179 ประเทศ
  • 35,000 K Line of Code




OpenStack Summit Sponsorship

openstack-sponsorship

Release Series

openstack-release-series

OpenStack Superuser Award Nominees เรียกได้ว่าบริษัทที่มีชื่อเสียงทั่วโลกที่ได้ทำเทคโนโลยี OpenStack ไปใช้งานแล้ว

  • China Mobile
  • City Network
  • Cloundwatt
  • DataCentered
  • Internap
  • MercadoLibre
  • ฯลฯ

OpenStack Foundation Structure

  • OpenStack Foundation คือ องค์กรไม่แสวงหาผลกำไร
    • Board Of Directors
    • Technical Committee (TC) ทำหน้าทีคอยดูภาพรวมทั้งหมดของ OpenStack
    • User Committee จะเป็นตำแหน่งที่ถูกเลือกโดยเหล่า Members ทั้งหลาย
    • Members ผู้ใช้งานทั่วไปที่ join เข้าเป็น member ของ OpenStack
  • OpenStack Project Teams
    • Projects Team Leads (PLTs) หน้าที่เป็นผู้นำสูงสุดของ Project นั้น ๆ ได้รับเงินเดือนจากบริษัทที่เป็น Sponsor
    • Active Project Contributor (APC) ทำหน้าที่ดูหลาย ๆ Project ไปพร้อมๆ กัน
    • Active Technical Contributor (ATC) การที่เรา Contribute Openstack อยู่เรื่อยๆ และจะถูกเลือกให้เป็นตำแหน่งนี้เอง

ติดตาม OpenStack Release State ได้แบบละเอียด ที่ลิ้งนี่

ตบท้ายได้แนะนำเทคนิคการไป Openstack Summit ในครั้งต่อ ๆ ไปแบบประหยัดจะต้องทำอย่างไร

ขอบคุณที่ติดตามครับผม

Yii1กับ Trick ต่างๆ ที่คุณอาจจะยังไม่เคยรู้

Yii1กับ Trick ต่างๆ ที่คุณอาจจะยังไม่เคยรู้ (จากประสบการณ์ใช้งานจริง)

ถึงแม้ว่า PHP Framework ที่ชื่อว่า Yii นี้ปัจจุบันจะพัฒนาไปถึง version 2 เป็นที่เรียบร้อยแล้ว แล้วจะเปลี่ยนไปใช้ version ใหม่ไปทำไมก็ในเมื่อ v.1.x ยังใช้งานไม่เต็มประสิทธิภาพเลย (ถึงแม้ใครจะบอกว่า version ใหม่ย่อมดีกว่าของเก่าเสมอ) ใช่สิก็ Content ของวันนี้เป็นเรื่อง Trick ของ Yii1 สิครับ ก็ต้องอวย v.1.x สิไม่แปลก

เริ่มตั้งแต่การ Setup Yii1 กัน

  • ก่อนอื่นก็ต้องไป Download Yii1 ที่ Yii1 Link Download
  • Unzip File yii-1.1.17.467ff50.zip และให้ Copy หรือ Rename Folder  ให้เป็นชื่อ application ของเราเอง ภายในให้เหลือแต่ folder ชื่อ framework, requirements
  • Run Command
cd demo

php framework/yiic wepapp app

Trick

1.ไม่อยากให้ URL มีคำว่า r=index.php
1. เปิด Url re-writing on Apache
2. สร้างไฟล์ .htaccess วางใน root path app ของเรา ภายในไฟล์ใส่คำสั่งดังต่อไปนี้

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . index.php

3. เปิดการใช้งาน urlManager ใน Configuration ที่ไฟล์ protected/config/main.php (ถ้า comment อยู่ในเอา comment ออก)
'urlManager'=>array(
  'urlFormat'=>'path',
  'rules'=>array(
      '<controller:\w+>/<id:\d+>'=>'<controller>/view',
      '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
      '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
  ),
  'showScriptName'=>false,
)
2.include internal javascript file end of body tag </body>
โดยปกติการ include file javascirpt เข้าไปใช้ใน project ของเรา

<script type="text/javascript" src="http://poolsawat.com/js/jquery.min.2.2.4.js"></script>

ในส่วนของ tag <head></head> แล้วถ้า dependencies ของในส่วนที่เราเรียกใช้มันเยอะมากละ มีผลต่อ performance แน่ ๆ
ดังนั้นการที่เราใส่ js ไฟล์ที่ tag body ก่อน </body> จะช่วยแก้ปัญหาเรื่องนี้ได้มาก 

สำหรับ Yii1 หากต้องการทำแบบนี้ให้ใช้คำสั่ง

$cs = Yii::app()->clientScript;
$cs->registerScriptFile($Yii::app()->baseUrl. '/js/jquery.min.2.2.4.js', CClientScript::POS_END);

เท่านี้ก็จะทำให้ไฟล์ js ของเราถูกโหลดหลัง html page แล้วครับ

3.echo data in JSON format ด้วย CJSON
$data = array('status' => true, 'message' => 'ok');

echo CJSON::encode($data);
4.Get form enctype=”multipart/form-data” ด้วย CUploadedFile::getInstanceByName(‘picture’)
<!-- form.php -->
<form class="ui form"  method="post" action="upload.php" enctype="multipart/form-data">
<input type="file" name="picture"  id="idInputPicture" />
</form>

<!-- upload.php-->
$file = CUploadedFile::getInstanceByName('picture');
$file->getError();
$file->getExtensionName();
$file->getName();
$file->getSize();
$file->getTempName();
$file->getType();
$file->saveAs(Yii::getPathOfAlias('webroot') . '/uploads/' . $file->getName());
5. use NOW() ด้วย CDbExpression Class
$model->field_date = new CDbExpression('NOW()');

$model->save();
* ใช้สำหรับการ save ผ่าน model

 

สรุปสิ่งที่ได้รับจากงานกิจกรรม Barcampbangkhen 2016

สรุปสิ่งที่ได้รับจากงานกิจกรรม Barcampbangkhen 2016

เมื่อวันอาทิตย์ที่ 13 พฤศจิกายน 2016 โดยจัดที่ ม.เกษตรศาสตร์ บางเขน ที่จัดเป็นประจำทุกปี โดยเป็นงานที่รวมเหล่าผู้ที่อยากรู้ อยากแบ่งปัน ความรู้มาพบเจอกัน โดยธรรมเนียมของงานก็ประมาณว่า ให้ผู้ที่อยากแชร์เรื่องราวต่าง ๆ ที่ไม่จำเป็นต้องเป็นเรื่องที่เกี่ยวกับสายเทคโนโลยีเพียงอย่างเดียวเรื่องอื่น ๆ ทั่ว ๆ ไปที่กำลังเป็นที่สนใจในขณะช่วงเวลานั้น มาแบ่งปันเล่าประสบการณ์ให้ได้รับฟัง ตัวอย่างเช่นหัวข้อ “ฝึกงานที่ญี่ปุ่นง่ายนิดเดียว (ที่เหลือยาก)”, “เมื่อหมอหมาอยากรักษาทามาก็อตจิ” เป็นต้น หรือแม่แต่เรื่อง “How to มีแฟนก่อนเรียนจบ” ซึ่งเป็นหัวข้อที่ได้รับเสียงฮือฮาเป็นอย่างมากในงานครั้งนี้

15050205_1199371473433593_1873296441_n-1

ช่วงเช้าผู้เข้าร่วมงานจะเริ่มเข้ามาลงทะเบียน ได้รับ เสื้อ, คูปองอาหาร, สติ๊กเกอร์ เป็นต้น สำหรับสติ๊กเกอร์ที่ได้รับมาจะเอามาใช้เพื่อโหวต Session ที่ตัวเองสนใจ และจะทำให้ Session นั้นได้ขึ้นเป็น Session ที่ได้ถูกบรรจุลงใน Board Session จริงpb130494

 

โดยแต่ละ Session ที่ถูกเลือกจะมีเวลาในการบรรยายประมาณ 25 นาทีต่อ 1 session ตาราง Session ในงานนี้ดูได้จาก Barcampbangkhen-sessions

pb130504

# Functional Programming with Javascript by Dan Itsara (แดน)

เนื้อหาใจความจะอธิบายถึงการเขียนโปรแกรมในรูปแบบคำสั่งเรียงต่อกัน มีเงื่อนไขมีการวนรอบ เนื้อหาใน session ไปอย่างรวดเร็วโดย Speaker จะเน้นแสดงตัวอย่างโค๊ดที่เป็นแบบโค๊ดที่เขียนแบบเขียนที่ไม่ได้ใช้ FP (Functional Programming) เข้ามาช่วย และเป็นแบบที่ใช้ FP เข้ามาช่วย สำหรับในหัวข้อนี้จำเป็นต้องมีทัษะในการเขียนโปรแกรมในระดับนึงเลย

ขอดีของการเอา FP เข้ามาช่วย

  • โค๊ดมีความกระชับ สั้น แต่อาจจะต้องใช้เวลาทำความเข้าใจในระดับนึง
  • ทำงานได้เร็ว กับข้อมูลที่ซับซ้อน ถ้าเปรียบเทียบกับโค๊ดที่ใช้ FP กับไม่ได้ใช้ FP
  • มีฟังก์ชันให้เลือกใช้อย่างมากมาย เช่น map, reduce, filter เป็นต้น
  • ฯลฯ

# Practical Maintainability ทำให้โค้ดดูแลง่าย “จริง” by Chris @ Taskworld

 เนื้อหาบรรยายเกี่ยวกับการ Maintain Code หรือแม้แต่จะ Code ขึ้นมาใหม่แม้ว่าจะเขียนโค๊ดแบบ Advance เทพมากแค่ใหนหากคนที่คอย Maintain ตามหลังไม่สามารถเข้าไปแก้ไขได้ง่าย ๆ ก็ไม่ถือว่าโค๊ดนั้นดูแลง่ายอยู่ดี และรูปแบบในการเลือก Dev เข้ามาใหม่ให้เหมาะกับงาน

# เรียนรู้อะไรมาบ้างกับการสร้าง Chatbot (The new era of Internet) by Wongnai (Chatbot Team)

บรรยายโดย CTO ของวงในเอง พูดถึงการนำ Chatbot (Line Chatbot)

สิ่งที่ควรทำนึงถึงเมื่อคิดจะทำ Chatbot

  • ทำให้ Bot เหมือนคนให้มากที่สุด
  • ให้ว่างเอกลักษณ์ของ Bot เป็นอย่างแรก เช่น อารมณ์ดี หรือ เครียด, สุภาพ หรือ ดิบเถื่อน เป็นต้น เพื่อทำเป็นที่จดจำได้ง่าย ตัวอย่างถ้าจะพูดถึง Bot ของวงในก็จะนึกถึงแต่เรื่องร้านอาหาร เป็นต้น
  • set กลุ่มคำถามเอาไว้เพื่อให้ตอบโต้ได้อย่างทันที
  • Emotion ช่วยได้เยอะมาก
  • คำศัพท์อาจจะไม่ต้องให้เป็นทางการมากตัวอย่าง เช่น ดี => สวัสดี, กินไรดี => กินอะไรดี, บัย => บาย เป็นต้น
  • เพิ่ม Question ในระหว่า Chat เพื่อความบันเทิง

# What comes next for the web? by @mikelopster @witoh

ไม่ใช่เรื่องใหม่สำหรับ PWA (Progrssive Web Application) เรียกว่า Session นี้ถูกใจ Dev สาย Web กันเลยการที่ Mobile กำลังมาแย่งส่วนแบ่งการใช้งานจาก Web App ทำให้ Web เอง อยู่นิ่งไม่ได้จึงทำให้เกิด PWA ขึ้น

PWA มีความสามารถอะไรบ้าง

  • สร้าง Icon บน Desktop ได้เหมือน Mobile App
  • ใช้งานได้ใน ขณะ Offine (เรียกข้อมูลใน Cache มาแสดง)
  • Push notification ได้เหมือน Mobile App
  • ต้องมี 3 สิ่งนี้ Reliable, Fast, Engaging
  • ฯลฯ

สิ่งที่ต้องคำนึง

  • ปลอดภัย (Security)
  • เร็ว (Fast)
  • วางใจ (Trust)

# DRY Workflow using Docker and Gitlab CI by Off (Glazziq)

Speaker จาก Glazziq แนะนำ Workflow การใช้งาน Docker ร่วมกับ Gitlab อธิบายการทำงานของ Docker แนบท้ายมีตัวอย่างโค๊ดการใช้งานให้ดู

# NO COMMENTS เลิกcomments เเล้วเขียนโค๊ดซะที by @mr_tawan

การ Comment โค๊ดบางสิ่งก็ไม่ควร Comment ไว้เพราะการเขียนโค๊ดที่ดีมันอธิบายการทำงานในตัวของมันเองอยู่แล้ว ผู้บรรยายยกตัวอย่างโค๊ดในประสบการณผู้บรรยายได้พบเจอมา โดยโค๊ดที่ถูกเขียนขึ้นมามีอายุ 20 กว่าปีมาแล้ว ส่วนที่ Comment ในโค๊ดไม่ได้ช่วยอะไรกับ Dev ในยุคปัจจบันเลย เพราะโดยปกตินิสัยคนเราแก้โค๊ดก็คงไม่ได้แก้ Comment กันทุกคน ทำให้เมื่อ version หลัง ๆ โค๊ดไม่ตรงกับ Comment บ้างก็มี ฉะนั้นให้หันมาใช้ Version Control กันเถอะ

# Location Intelligence – wifi data and big data by Khum Pimsiri Ponsap(Data Scientist)

เนื้อหาเกี่ยวกับว่าเราจะนำข้อมูลที่เกี่ยวกับ Wifi มาใช้งานแบบใดได้บ้าง ยกตัวอย่างการดักจับ Wifi ในห้างสรรพสินค้า บ่งบอกได้ว่ามีการใช้ข้อมูลบริเวณใด มาก น้อย ดูลักษณะของข้อมูลลูกค้าที่เข้ามาใช้บริการในห้างนั้นซ้ำ ๆ และสามารถนำข้อมูลไปวิเคราะห์เพื่อช่วยธุรกิจสร้างผลกำไร ต่อไปได้

# Security Discussion by [email protected]!N

Session ก่อนที่ผมจะกลับบ้านเลือกที่จะเข้าไปฟัง session นี้ ไอ้ตัวผมเองก็เป็น Dev ไม่ค่อยจะใส่ใจเรื่อง Security เท่าไหร่ เลยอยากให้ความสำคัญกับเรื่องนี้ เลยเลือกที่จะเข้าไปฟัง ผู้บรรยายเป็นตัวแทนจากหน่วยงาน Owasp Thailand ซึ่งเป็นองค์กรไม่แสวงหาผลกำไรมี community ระดับโลก วัตถุประสงค์เพื่อส่งเสริมและพัฒนาการรักษาความปลอดภัยของโปรแกรมประยุกต์ (Application) ให้ดียิ่งขึ้น ติดตามข่าวสารความเคลื่อนไหวได้ที่ Owaspthailand Page




Array Methods ต่าง ๆ ใน Javascript พร้อมตัวอย่างการเรียกใช้งาน

Javascript Language ต้องยอมรับเลยว่ามาแรงอย่างมาก เรียกว่าไม่รู้ไม่ได้แล้ว ทุกภาษาโปรแกรมมิ่งจะต้องมี Data Collection แน่นอน Javascript ก็ เช่นกัน Array ก็เป็นการเก็บข้อมูลประเภทหนึ่งใน Javascript และ Javascript ก็สร้าง methods สำหรับใช้งานกับ Array ไว้ให้หลายแบบตามการใช้งาน วันนี้เลยอยากที่จะเอาตัวอย่างโค๊ดง่าย ๆ สำหรับการเรียกใช้งาน Array Methods แต่ละ Method ว่าใช้งานอย่างไร

// สร้าง Array Data เตรียมไว้ก่อน
const data1 = [1,2,3,4,5,6,7,8,9];
const data2 = [11,12,13,14,15,16,17,18,19];
const data3 = [21,22,23,24,25,26,27,28,29];
const data4 = [31,32,33,34,35,36,37,38,39];
console.log('_data1 :: ',data1);
console.log('_data2 :: ',data2);
console.log('_data3 :: ',data3);
console.log('_data4 :: ',data4);

// console.log()
=> _data1 :: 1,2,3,4,5,6,7,8,9
=> _data2 :: 11,12,13,14,15,16,17,18,19
=> _data3 :: 21,22,23,24,25,26,27,28,29
=> _data4 :: 31,32,33,34,35,36,37,38,39

// map => สร้าง Array ชุดใหม่ โดยมีเงื่อนไขบางอย่าง
const _map = data1.map(x => x+1);
console.log('_map [+1] data1 :: ',_map);
=> _map [+1] data1 :: 2,3,4,5,6,7,8,9,10

// filter => กรองข้อมูล Array จากเงื่อนไขบางอย่าง
const _filter = data1.filter(x => x%2 == 0)
console.log('_filter [x%2 == 0] data1 :: ',_filter);
=> _filter [x%2 == 0] data1 :: 2,4,6,8

// concat => รวม Array หลาย Array เป็น Array เดียว
const _concat = data1.concat(data2);
console.log('_concat data1 & data2 :: ',_concat);
=> _concat data1 & data2 :: 1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19

// copy => Copy element ใน Array ตามตำแน่งที่กำหนด
const _copy = data1.copyWithin(3,0);
console.log('_copy [3,0] data1 :: ',_copy);
=> _copy [3,0] data1 :: 1,2,3,1,2,3,4,5,6

// every => ตรวจสอบ element ใน Array
const _every = data2.every( x => x > 9 );
console.log('_every [ > 9] data2 :: ',_every);
=> _every [ > 9] data2 :: true

// fill => replace element ใหม่ แทนที่ element เดิม
const _fill = data3.fill(1);
console.log('_fill [1] data3 :: ',_fill);
=> _fill [1] data3 :: 1,1,1,1,1,1,1,1,1

// pop => ค้นหา element ตัวสุดท้าย
const _pop = data1.pop();
console.log('_pop data1 :: ',_pop);
=> _pop data1 :: 9

// push => เพิ่ม element ใน Array โดยจะต่อท้าย
const _push = data2.push(999);
console.log('_push [999] data2 :: ',data2);
=> _push [999] data2 :: 11,12,13,14,15,16,17,18,19,999

// reduce => for เก็บค่าไว้ เหมือนการ loop sum
const _reduce = data1.reduce((x,y) => x+y)
console.log('_reduce data1 :: ',_reduce);
=> _reduce data1 :: 21

// reverse => สลับ element ใน Array จากก่อน -> ท้าย เป็น ท้าย -> ก่อน
const _reverse = data1.reverse();
console.log('_reverse data1 :: ',data1);
=> _reverse data1 :: 9,8,7,6,5,4,3,2,1

// shift => ลบ element แรกใน Array
const _shift = data2.shift();
console.log('_shift data2 :: ',data2)
console.log('_shift :: ',_shift);
=> _shift data2 :: 12,13,14,15,16,17,18,19,999

// slice เลือก element ใน Array โดย index
const _slice = data2.slice(5,2);
console.log('_slice [5,2] data :: ',data2);
=> _shift :: 11
=> _slice [5,2] data :: 11,12,13,14,15,16,17,18,19

// som => ตรวจสอบ element ใน Array
const _som = data1.some( x => x = 5);
console.log('_som [=5] data1 :: ',_som);
=> _som [=5] data1 :: true

// sort => เรียงลำดับ element น้อย -> มาก
const _sort = data1.sort();
console.log('_sort data1 :: ',_sort);
=> _sort data1 :: 1,2,3,3,4,5,6,7,8,9

// splice => เพิ่ม new element เข้า Array โดยระบุตำแหน่ง
const _splice = data4.splice(2, 0, -99,0)
console.log('_splice [2, 0, -99,0] data4 :; ',data4);
=> _splice [2, 0, -99,0] data4 :; 31,32,-99,0,33,34,35,36,37,38,39

// unsgift => เพิ่ม new element ตำแหน่งหน้าสุด
const _unshift = data1.unshift(-99,0);
console.log('_unshift [-99,0] data1 :: ',data1);
=> _unshift [-99,0] data1 :: -99,0,1,1,2,2,3,3,4,5




บทความนี้ฝากไว้เท่านี้ครับ

ขอบคุณภาพประกอบจาก https://www.safaribooksonline.com/library/view/javascript-and-jquery/9781118531648/17_chapter12.html