본문으로 바로가기

JavaScript(ES6)+jQuery, 2024

category Web Programming 2024. 3. 25. 22:02

 

▼Refreences

Babel is a JavaScript compiler. [Try it!] | 2024.04.03

만들어 가며 알아보는 React: React는 왜 성공했나 | 2022.07.22

https://ko.javascript.info/

https://dbcut.com/ (Desing community portal)
https://gsap.com/ (GSAP)

https://swiperjs.com/  (Swiper - Sliding~ 2024.04.01) 

https://github.com/haloa19/react (참고:리액트 수업 내용 및 소스)

 

▼VSCode extensions  

ES7 React/Redux/GrapQL/React-Native 
 
Babel 플러그인 기능과 함께 ES7의 JavaScript 및 React/Redux 스니펫을 제공
Code Runner
 
Code Runner
Code를 바로 실행하고 Output에서 확인할 수 있는 확장.
( Run code snippet or code file for multiple languages: C, C++, Java, JavaScript, PHP, Python, Perl, Perl 6, Ruby, Go, Lua, Groovy, PowerShell,..)

Error Lens
코드오류시, 에디터에 직관적으로 바로 표시
(Improve highlighting of errors, warnings and other language diagnostics.)
▼Chrome extensions  
  Web Developer 현재 웹페이지의 HTML, CSS를 변경(Disable)해서 표시
  Fatkun Batch Download Image get tab images
▼jQuery Plugin  
  제이쿼리 갤러리 플러그인(jQuery Plugin) :: isotope.js - 얼핏 보면 핀터레스트st 이라고도 볼 수가 있는 Filter&Sort Layout 플러그인.
- 카테고리에 맞춰서 이미지를 분류하고 필터링해주는 그리드를 만들 때 사용하면 유용.
▼ Sites  
GSAP(GreenSock  Animation Platform): 타임라인 기반 자바스크립 애니메이션 라이브러리. https://gsap.com/
   
Lenis: Smooth Scroll, 플랫폼을 사용하는 동시에 스크롤 경험을 표준화하고 매우 부드러운 탐색 기능으로 웹사이트를 강화하기 위해 구축된 오픈 소스 라이브러리 https://darkroom.engineering/
React+Vite: 프론트엔드 개발도구(빌더), 예전의 npm대체. https://ko.vitejs.dev/
window.requestAnimationFrame(), 웹 애니메이션 최적화 javascript 내장함수
   

 

▼강의노트

https://brainy-rainstorm-177.notion.site/03-25-05-27-JS-74746f7f11624baba4096707c0eb865f

https://www.w3schools.com/jquery/default.asp

https://www.w3schools.com/js/default.asp

DOM 제어, 속성/스타일 제어, event 

 

▼ https://www.w3schools.com/js/default.asp

/* ▼ JS HTML DOM > DOM Document */
// Finding HTML Elements
let element = 
document.getElementById(id); // HTML Object or null
document.getElementsByTagName(name); // HTMLCollection[] or []
document.getElementsByClassName(name); // HTMLCollection[] or []
document.getElementById("myList").children[0]; // if myList=ul then children=li
// Changing HTML Elements
element.innerHTML =  new html content;
element.attribute = new value;
element.setAttribute(attribute, value)
element.style.property =  new style;
// Adding and Deleting Elements
document.createElement(element); // HTML Object
document.appendChild(element);
document.replaceChild(new, old);
document.removeChild(element);
document.write(text);
//Adding Events Handlers
document.getElementById(id).addEventListner("click", function() {...});
document.getElementById(id).onclick = function(){...}
//Finding HTML Objects
document.domain
document.baseURI / document.documentURI
...

 

/* ▼ JavaScript > JS Tutorial > Array Methods */
Array push() // 뒤에 추가(length+1)
Array pop()  // 리스트의 마지막 요소 꺼내서 반환 (length-1)
Array length
Array toString()
Array shift() / unshift()
Array delete()
Array concat()
Array copyWithin()
Array flat()
Array splice()  // .splice(idx, 1) 리스트의 idx부터 1건 삭제
Array toSpliced()
Array slice()
Array at()
Array join()

/* ▼ Javascript > JS Browser BOM > JS Timing */
window.setTimeout(function, milliseconds) 
window.clearTimeout(timeoutVariable)
window.setInterval(function, milliseconds)
window.clearInterval(timerVariable)

 

/* ▼ localStorage */
localStorage.setItem(key, value);
localStorage.getItem(key);
localStorage.setItem("obj1", JSON.stringify({"aaa":111, "bbb":222}));
let obj1 = JSON.parse(localStorage.getItem("obj1"));
console.log("obj1:", obj1);
console.log("localStorage.length:", localStorage.length);
localStorage.removeItem(key);
localStorage.clear();

 

▼jQuery vs Javascript

/* ▼ 문서로딩(DOM생성) 후 */
// jQuery
$(function() {...});
//or
$(document).ready(function() {...});

// Javascript
window.onload = function() {...};
//or
window.addEventListener("load", function(event) {...});
//or
addEventListener("DOMContentLoaded", (event) => {...});

/* ▼ 선택자(Selector) */
// jQuery
$("p")
$("#test")
$(".test")
$(this)
$("p:first")
$("tr:even")
$('.box p')

// JavaScript
document.getElementById("intro");
document.getElementsByTagName("p");
document.getElementsByClassName("intro");
document.querySelector("p");
const list = element.querySelectorAll(".example");

 

/* ▼ DOM Traversing */
// jQuery
// 상위 요소 탐색                    
$(this).parents(".hslide").find("figure img").attr("src", href);
$(this).parents("li").css({"color": "#f00"});
$(this).parent("li").siblings().find("a").removeClass("on");
$("span").closest("ul")
// 하위 요소 탐색
$(this).children("a").addClass("on");
$("ul").find("span").css({"color": "#f00", "border":"2px solid blue"});
// 형제 요소 탐색
$(this).parent("li").siblings().find("a").removeClass("on");
$("li.start").next().css({"color": "#f00", "border":"2px solid blue"});
$("li.start").prev().css({"color": "#f00", "border":"2px solid blue"});
// 필터링
$("p").eq(1).css({"color": "#f00", "border":"2px solid blue"});
$("li").filter(".start");
$("li").not(".start);

// Javascript
const element = document.getElementById("memo-list").parentNode.nodeName;
const closest = element.closest(".contariner");
document.body.children; //HTMLCollection[]
element.nextElementSibling.textContent;
element.previousElementSibling.innerHTML;

/* ▼ Event */
$("p").click();
$("p").on("click", function(){
  
});
$("p").on({
  mouseenter: function(){
    $(this).css("background-color", "lightgray");
  },
  mouseleave: function(){
    $(this).css("background-color", "lightblue");
  },
  click: function(){
    $(this).css("background-color", "yellow");
  }
});
$("button").click(function(){
  $("input").trigger("select"); // 이벤트 강제실행
});
$("button").click(function(){
  $("p").off("click"); // 이벤트 실행중지
});

// Javascript
element.addEventListener("click", function() {
  document.getElementById("demo").innerHTML = "Hello World";
});
dispatchEvent(event);
removeEventListener('click', listener);

if (document.getElementById("check").checked) {
  event.stopPropagation(); // 이벤트 전파 중단
}

// CSS 이벤트 제어
div.ex1 { pointer-events: none; }
div.ex2 { pointer-events: auto; }
/* ▼ Content get/set */
// jQuery
// get - text/html/value
$(this).text(), html(), and val();
// set
$(this).text("new text"), html("!"), and val(111);

// Javascript
textContent, innerHTML, value, outerHTML

/* ▼ Attributes */
// jQuery
$('li a').click(function(e){
    e.preventDefault()
    let href= $(this).attr('href')//get
    $('figure img').attr({'src':href})
});
// Javascript
document.querySelectorAll('li a').forEach(function(link){
        link.addEventListener('click',function(e){
        e.preventDefault();
        lef href=this.getAttribute('href');
		document.querySelector('figure img').setAttiribute('src',href); 
	});
});

/* ▼ Class */
// jQuery
$('li').removeClass('on');
$(this).addClass('on');
const sw=$(this).hasClass('active');
$(this).toggleClass('active');
// Javascript
document.querySelectorAll('li').forEach(function(item) {
	item.classList.remove('on')
});
this.classList.add('on');
const sw=this.classList.contains('active');
this.classList.toggle('active');

▼ ES6

  (updated: 2024.04.22)

 

1. 변수,상수

  선언 할당
var 재선언 재할당
let X 재할당
const X X

 

// 상수 객체는 프로퍼티 추가/수정/삭제 가능
const mannerMan = {
    name: "길동군",
    greeting : () => {
        console.log("Manners maketh man.");
    }
}
mannerMan.greeting();
mannerMan["greeting"]();

 

2-1. 자료형(primitive vs object), 형변환(Type Casting): 묵시적 vs 명시적

// Primitive Type:
String, Number, Boolean, null, undefined
// Object Type:
Object (=pointer형 변수)
  └ Array, Function RegExp

let obj1 = {nm: "길동이" }
let obj2 = obj1; // 얕은 복사(Shallow Copy): 같은 주소값 참조
let obj3 = {...obj1}; // ★깊은 복사(Deep Copy): 새로운 객체 주소 참조

// Type Casting: to Number/String/Boolean
// 1. to Number: Number(), parseInt()
console.log(Number("10"), Number("10건")); // 10 NaN
console.log(parseInt("10건")); // 10
console.log(parseInt("A10")); // NaN (앞자리에 숫자가 위치할 경우에만 유효)
// 2. to String
console.log(String(undefined), String(null); // 'undefined' 'null'
console.log(String(true), String(NaN)); // 'true' 'NaN'
// 3. to Boolean
console.log(Boolean("Hi!"), Infinity(Infinity)); // true true
console.log(Boolean(undefined), Boolean(null)); // false false
console.log(Boolean(0), Boolean(NaN), Boolean("")); // false false false

 

3. template literals 문법

// ``(backtick)을 이용한 template literals 문법 
const ramenList = [
{ brand: '농심',
  items: ['신라면','짜파게티','참치마요','둥지냉면']},
{ brand: '오뚜기',
  itmes: []}
];
// tag templates
function fn(strings, brand, items) {
 let str;
 if(undefined === items) {
    str = brand + "의 라면은 재고가 없습니다!";
 } else {
    str = strings[0] + brand + strings[1] + items;
 }
 return str;
}
/// template literals
console.log(fn`구매가능한 ${ramenList[0].brand}의 라면 : ${ramenList[0].items}`);
console.log(fn`구매가능한 ${ramenList[1].brand}의 라면 : ${ramenList[2].items}`);
//구매가능한 농심의 라면 : 신라면,짜파게티,참치마요,둥지냉면
//오뚜기의 라면은 재고가 없습니다!

/// multi-line strings (\n 대신)
console.log(`string text line 1
string text line 2`);

/// nesting templates(중첩 템플릿)
const classes = `header ${ isLargeScreen() ? '' :
                `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;

let s = String.raw`xy\n${1+1}z`;
console.log(s);     //xy\n2z

 

3. 연산자(Operator): null 병합연산자(??), typeof num1, obj1 instanceof Object

/* null병합 연산자;Nullish coalescing assignment (??, ??=) 
   (true/false가 아닌 빈값(null/undefined)인지 여부만을 체크.
    따라서 NaN,Infinity는 PASS!)
 */
console.log(null ?? ''); // ''
console.log(undefined ?? 0); // 0
console.log(undefined ?? null); // null (첫 값이 true이면 연산종료)
console.log(null ?? undefined); // undefined (첫 값이 false이면 다음값을 취한다)

let x = null;
x ??= 10; // x ?? (x = 10)

/* typeof */
console.log(typeof Date); // Function
console.log(typeof Math); // object
console.log(typeof null); // object
console.log(typeof undefined); // undefined

 

4. 조건문, 반복문

//조건: if, switch
//반복: while, do while, for, for..in, for..of, Array.forEach()

 

5. 함수
├ 함수 선언식 vs 함수 표현식

함수 인수(argument)와 매개변수(parameter)

함수 반환 return

 콜백(callback): 다른 함수에 인수로 전달되는 함수. 주로 다른 함수의 처리를 기다려야하는 비동기 함수에서 사용.
└ Arrow 함수: 생략표기법

// ▼Arrow Function의 생략표기법
let a = (name) => { return name + " hello!"; }
// ()안의 매개변수가 1개 & 실행명령문 1줄인 경우, return / {} / () 생략 가능.
let a = name => "hello!";

// 콜백함수 활용 : 비슷한 구조의 겹치는 영역 활용!?
function repeat(count, callbackFn) {
    for(let idx = 1; idx <= count ; idx++) {
        callbackFn(idx);
    }
}
repeat(5, (idx) => { console.log(idx); });
repeat(5, (idx) => { console.log(idx * 2); });

 

6. 스코프; global vs local scope

- hoisting,호이스팅, "끌어올리다"

 (예를 들어 함수를 하단에 정의해도 상단에서 호출 가능. 단, 함수표현식은 호이스팅 대상이 아님)

 

7. 객체

// 1. 객체생성 방법
let obj1 = new Object(); // 객체 생성자
let obj2 = {}; // 객체 리터럴(간결해서 주로 사용하는 방법)

// 2. 겍체 프로퍼티(속성) 정의
let mannerMan = {
  name: "길동이",
  age: 36,
  greeting: "Manners maketh man.",
  extra: {},
  "cat like grade": 10,
};

// 3. 객체 프로퍼티(속성) 접근 or 추가 방법
// - 점(.) 표기법 vs 대괄호([]) 표기법

// 4. 프로퍼티 삭제 
delete mannerMan.extra, mannerMan["cat like grade"];
delete mannerMan.XX; // 없는 속성 삭제됨.

// 5. 프로퍼티 존재 확인
let rslt1 = "name" in mannerMan; // true
mannerMan.hasOwnProperty("XXX"); // false

// ★ primitive vs object 
// = reference_value vs pointer_value
// = 값이 바뀌면 새로운 값 참조(new) vs 값이 바뀌면 이전값 변경(overwrite)
let mmShallowCopy = mannerMan; // 얕은 복사: 참조값 복사
let mmDeepCopy = {...mannerMan}; // 깊은 복사: 새로운 값의 생성
console.log(mannerMan === mmShallowCopy); //▶true (얕은 비교, 참조값비교)
console.log(mannerMan === mmDeepCopy); //▶false (얕은 비교)
console.log(JSON.stringfy(mannerMan) === JSON.stringfy(mmDeepCopy)); //▶true (깊은 비교)

 

8. 배열

// 1.배열 생성
let arr1 = new Array(); // 배열 생성자
let arr2 = []; // 배열 리터럴(주로 사용) 
arr1 = [
 1, 2, 3, Infinity, -Infinity, NaN,
 true,
 "Manner makes man.",
 null,
 undefined,
 () => {},
 {},
 []
];

// 2. 배열요소 접근
// 3. array join()
console.log(arr1.join()); // = arr1.join(",")
//▶1,2,3,Infinity,-Infinity,NaN,true,Manner makes man.,,,() => { },[object Object],

 

9-1. Truthy & Falsy

// Falsy
let f1 = undefined;
let f2 = null;
let f3 = 0;
let f4 = -0;
let f5 = NaN; // isNaN() 으로도 체크
let f6 = "";
let f7 = 0n; // Big Integer

// Truthy (=7가지 Falsy한 값을 제외한 나머지)
let t1 = "hello";
let t2 = 123;
let t3 = [];
let t4 = {};
let t5 = () => {}
let t6 = new Object;
let t7 = 123 + "";
let t8 = -Infinity; // isFinite()로도 체크

// ▼ Object case
let person = { name: "Elin Kwon", age: 27, team: "블랙핑크" }
console.log(1, (person && person.name) || "no result");
console.log(2, (person.name && person) || "no result");
console.log(3, (person && person.XX) || "no result");
console.log(3, (person.XX && person) || "no result");

// null병합 연산자는 빈값(null or undefined)인지를 체크
// Truthy & Falsy는 true/false를 체크

 

9-2. 단락평가(Short-Circuit Evaluation)

: 논리 연산에서 첫 번째 피연산자의 값만으로 해당 식의 결과가 확실할 때, 두 번째 값은 평가하지 않는 javascript의 특징.

// 단락평가 활용
let person = { name: "Elin Kwon", age: 27, team: "블랙핑크" }

// 1. A && B : if A is Truthly then B else false.
const testAndT = person && person.name; // = person.name
const testAndF = person && person.name; // = false
if (!testAndF) { 다음처리.. }

// 2. A || B : if A is Truthly then A else B.
const testOr = person || "person값 없음";

 

10.구조분해 할당(destructuring assignment)

; https://ko.javascript.info/destructuring-assignment

// 1.배열의 구조분해 할당
let arr1 = [1,2,3];
let [one, two, three, four = 4, no] = arr1; // 초기화(no=undefined)
console.log(one, two, three, four, no);

// 2.객체의 구조분해 할당
let person = {
    name: "Elin Kwon",
    age: 27,
    team: "블랙핑크"
}
// 새로명명 => property:newVariable
let {age, name:nm, team, color="black"} = person;
console.log(age, name, team, color);

// 3. 함수의 매개변수 받기
const funcA = ({name,age},[onw,two]) => {
  console.log(name, age, one, two);
}
funcA(person, arr1);

 

11. 스프레드 연산자(spread operator)와 Rest 매개변수[...: 연결자 or 값으로써]

// Spread Operator (펼치다,흩뿌리다)
let arr1 = [1,2,3];
let arr2 = [4,...arr1,5,6];
console.log(arr2);

let person = { name: "Elin Kwon", age: 27, team: "블랙핑크" }
let obj2 = { ...person, d: "DDD", e: "222"}
console.log(obj2);

const funcB = (a, b, c, d) => {
  console.log(a,b,c,d);
}
funcB(...arr1); // ▶1 2 3 undefined
funcB(arr1); // ▶(3) [1, 2, 3] undefined undefined undefined

const funcC = ({name, age, b = undefined}) => { 
  // 객체속성이 아닌 b는 초기값이 없으면 error
  // ;Uncaught TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function
  console.log(name, age, b);
}
funcC(...person);

// Rest Parameter (나머지 매개변수, 반드시 마지막 매개변수)
function restExam(param, ...rest) {
  // param=1, [2,3]
  console.log(param, rest);
}
restExam(1,2,3); //▶

const obj = { a: 1, b: 2, c: 3 }
const { c, ...obj3 } = obj; // c를 제외한 obj값을 가지는 obj3 새로 생성
console.log(obj3);

// spread operator는 펼치고, rest parameter는 모은다.
// spread operator는 주는 쪽이고, rest parameter는 받는 쪽이다.
// spread operator는 기존의 변수를 사용하고, rest parameter는 새로운 변수를 만든다.

 

12-1.배열&객체  순회(Iteration): for of, for in

//▼ 배열 순회
// 1. 반복문과 배열index 사용
// 2. for of 반복문(only 배열용)
let arr1 = [1,2,3,4,5];
for (let item of arr1) { xxx; /*unknown index*/ }

//▼ 객체 순회
// 1. Object.keys(), Object.values()
// 2. for in 반복문
let person = { name: "Elin Kwon", age: 27, team: "블랙핑크" }
let keys = Object.keys(person); // 키값을 array로 담기
for (let key of person) { console.log(person[key]); }
for (let key in person) { console.log(person[key]); }
let values = Object.values(person);
for (let val of values) { console.log(val); }

 

12-2.배열 요소조작: push/unshift, pop/shift, slice, concat

// 1. push(뒤에) & unshift(앞에) 요소 추가
let arr1 = [1,2,3];
let length = arr1.push(4,5,6,7);
let length = arr1.unshift(0, -1); // ▶0,-1,1,2,..

// 2. pop(뒤에서) & shift(앞에서) 요소 꺼내기
const poppedItem = arr1.pop();
const shiftItem = arr1.shift();
/// shift, unshift는 push,pop 보다 속도가 느리다.

// 3. slice : 배열의 특정범위를 잘라내서 새로운 배열 반환
// array.slice(startIndex, endIndex)
// - startIndex부터 ~ endIndex-1까지 잘라낸다.
// - endIndex없으면 끝까지 자른다
// - -N이면 뒤부터 자른다
let arr2 = [1,2,3,4,5];
let newArr1 = arr1.slice(2,4); //▶3,4
let newArr2 = arr1.slice(-4); //▶2,3,4,5

// 4. concat : 두 배열을 이어 붙여서 새로운 배열 반환
let arr3 = [6,7];
let newArr3 = arr2.concat(arr3);

 

12-3.배열 순회&탐색, 배열 변형: forEach, includes, indexOf, findIndex, find

let arr1 = [1,2,3];

// 1. forEach
arr1.forEach((item, idx, arr/*전체Array*/) => {
  console.log(item, idx, arr);
});

// 2. includes(value): value이 있는지 여부

// 3. indexOf(value): 
//  - 찾는 값의 인덱스 반환 없으면 -1
//  - 얕은 비교이므로 object type 사용불가.

// 4. findIndex(callbackFn): callbackFn를 만족하는 값의 인덱스 반환
const idx2 = arr1.findIndex(e => e % 2 === 0); //▶1 (첫번째 짝수)

// 5. find: callbackFn를 만족하는 값(or객체)를 반환
const ramenList = [
{ brand: '농심',
  items: ['신라면','짜파게티','참치마요','둥지냉면']},
{ brand: '오뚜기',
  itmes: []}
];

const found = ramenList.find((item) => item.brand = "농심");
//▶{brand: '농심', items: Array(4)}

 

12-4. 배열 변형: filter, map, reduce, sort, join

// 1. filter : 조건을 만족하는 요소를 새로운 배열로 반환
const obj1 = [
    { nm: "홍길동", age: 25 },
    { nm: "이순희", age: 31 },
    { nm: "김좌진", age: 45 },
];
console.log(obj1.filter(v => v.age < 35));

// 2. map : 배열의 요소별로 순회하면서, 콜백함수내 반환결과를 새로운 배열로 반환
const rslt1 = obj1.map((e, idx, arr) => {
  const ageGroup = Math.trunc(e.age / 10) * 10 + "대";
  // ▼obj1 변형CASE
  //e.ageGroup = ageGroup;
  //return e; // obj1 동일 주소(ShallowCopy)
  // ▼obj1 DeepCopy
  return {...e, ageGroup};
});
console.log(rslt1);
const obj1NmList = obj1.map(e => new Object({nm: e.nm}));
// └배열 obj1의 nm요소로만 이루어진 새로운 배열 생성

// 3. sort : 배열을 사전순(문자열비교) 정렬(원본배열 변형)
// [ 양수반환: b, a / 음수: a, b / === : origin]
let strings = ["orange", "banana", "melon", "apple"];
const sortedStrings = strings.sort();
console.log("sortedStrings: ", sortedStrings);

let numbers2 = [10,3,5];
numbers2.sort((a, b) => {
    return a - b; // 오름차순
});
console.log(numbers2);

// 4. toSorted : 배열을 사전순(문자열비교) 정렬한 새로운 배열 반환.
// (2023.07이전 버전은 미지원)
const sortedStrings = strings.toSorted();

// 5. join(구분자/기본값은 쉼표) : 배열의 모든 요소를 하나의 문자열로 합쳐서 반환.
const obj1 = ["hello", "ES6", "javascript", "world"];
const joinedStr = obj1.join(""); //▶ 'helloES6javascriptworld'

// 6. reduce (부분합)
let numbers = [1,2,3,4,5];
const rslt2 = numbers.reduce((prev, curr, idx) => { 
    console.log(idx, ": ", prev, " + ", curr, " = ", prev+curr);
    return prev+curr;
});
console.log(rslt2);

 

13. Date 객체

// 1. 생성
let date1 = new Date();
let date2 = new Date("2024-05-01"); //ISO:국제표준형식
let date4 = new Date(2024,05,01,19,49,0);
let date5 = new Date("2024.05.01.19:34:30");
let date6 = new Date("2024/05/01.19:34:30")
let date7 = new Date("2024/500/1/19:49:00"); // Invalid date

// 2.TimeStemp
// 1970.01.01 00:00:00(UTC+0)로 부터 지난 ms
let ts1 = new Date().getTime();
let date6 = new Date(ts1);

// 3.시간 요소 추출
// - Month()는 0부터 시작.
let date3 = new Date("2024/5/1/19:49:00");
console.log(date3.getFullYear(), date3.getMonth() + 1, date3.getDate());
console.log(date3.getHours(), date3.getMinutes(), date3.getSeconds());
//date3.setFullYear(2023);
//date3.setMonth(6); //...이하동문 

// 4.시간 포맷
date3.toDateString(); // ▶Wed May 01 2024
date3.toLocaleString(); // ▶2024. 5. 1. 오후 7:49:00
date3.toLocaleDateString(); //▶2024. 5. 1.

 

14. 동기,비동기 ; Promise, Fetch, Async, Await

* JavaScript 엔진은 only 1 스레드로 동작하고, 비동기 작업은 Web APIs에 넘겨서 처리.

Javascript 비동기 처리 feat. Web APIs

// 1. callback hell
function orderFood(food, callbackFn) {
    const orderedFood = `${food}`;
    setTimeout(() => {
        callbackFn(orderedFood);
    }, 3000);
}

function freezeFood(food, callbackFn) {
    const freezedFood = `냉동시킨 ${food}`;
    setTimeout(()=> {
        callbackFn(freezedFood);
    }, 2000);
}

orderFood("로제떡볶이", (orderedFood) => {
    console.log(orderedFood);

    freezeFood(orderedFood, (freezedFood) => {
        console.log(freezedFood);
    });    
});

 

14-1. Promise객체: 비동기 작업을 감싸는 객체.

  ├ 비동기 작업을 감싸는 형태. 비동기 작업 실행, 상태관리, 결과저장, 병렬실행, 다시실행 등 기능.

  └ Promise 상태: 대기(Pending) → if 해결(resolve)되면 then 성공(Fulfilled) else /*거부(reject)되면*/ 실패(Rejected)

// tag template
const fireWorksTag = (strings, symbol) => {
    let str = '';
    for(i = 0 ; i < 30; i++) { str += symbol; }
    return (strings[0] ?? "") + str + (strings[1] ?? "");
}
// promise function
const fireWorks = (symbol, tabCount) => {
    const delay = Math.floor(Math.random() * 5000);
    const promise = new Promise((resolve, reject) => {
        if (delay >= 2000) {
            console.log(String(tabCount).padStart(2,"0"),": ", Array(tabCount+1).join("\t"), fireWorksTag`[${symbol}]`, delay / 1000, "s");
            resolve({delay, symbol}) 
        } else {
            reject("실패: 5초 미만의 딜레이 값입니다["+delay / 1000+"s, " + symbol + "]");
        }
    }, delay);

    return promise;
}

const fire1 = fireWorks("◎", 0)
.then((result) => {
    return fireWorks("◆", 1);
})
.then((result) => {
    return fireWorks("♣", 2);
})
.catch((error) => {
    // 이전 모든 비동기 작업 실패시 도착 지점
    console.log(error);
});

/*
[Running] node "c:\byhouProjects\workspace\onebite-react2024\2-13.Promise.js"
00 :   [◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎◎] 2.325 s
01 :  	 [◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆] 2.388 s
실패: 5초 미만의 딜레이 값입니다[0.172s, ♣]
*/

 

14-2. Async/Await

async: 비동기 함수로 변경(내부에  이미 Promise가 있으면 no효과)

await: async 함수 내에서만 사용. 비동기 함수 처리가 끝날때까지 대기. 

Fetch, 

 

 

■ Node.js 

Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임(실행환경,구동기)이다 - Run JavaScript Everywhere.

 

1. 설치 & 실행

// 0. node.js 설치 & 버전확인
> node -v
> npm -v

// 1. package create
> npm init  // package.json 생성됨.

/* package.json▼
  {
    "name": "proj-name",
    "version": "0.1.0",
    "description": "2024.05",
    "main": "index.js",
    "scripts": {    
      "test": "echo \"Error: no test specified\" && exit 1",
      // ▼ 실행 명령 정의: npm run start
      "start": "node src/index.js"
    },
    "author": "",
    "license": "ISC"
  }
*/

// 2. src/index.js 생성
console.log("Hello, Node.js world!");

// 3. js 실행
> node src/index.js
// 또는 package.json > scripts > "XXX" 정의하여 사용 
> node run start

 

 

2. Node 모듈 시스템

  ES Module(ESM) CommonJS(CJS)
문법 export
import
module.exports = {};
const moduleName = require("./file");
동작방식 비동기 동기
사용환경 웹브라우저(ES6), NodeJS NodeJS
패키지 관리 package.json, npm require

 

 

/* CommonJS */

/* counter.js */
//-----------------------------------------------
// 1
// module.exports = {
//     count: 0,
//     increase : function() {
//         this.count++;
//     }
// }

//-----------------------------------------------
// 2
// function isEmpty(a) {
//     return !(a ??= undefined || length(trim(String(a))) > 0);
// }
// function isNumber(a) {
//     return typeof a === "number" && a !== NaN;
// }
// module.exports = {isEmpty, isNumber}

//-----------------------------------------------
// 3
// export let count = 0;
// export function increase() {
//     count++;
// }

//-----------------------------------------------
// 4. 'default': import하지 않아도 자동import
export function isEmpty(a) {
    return !(a ??= undefined || length(trim(String(a))) > 0);
}
export function isNumber(a) {
    return typeof a === "number" && a !== NaN;
}
export default function isCheck(a) {
    return typeof a === "number" && a !== NaN;
}

//-----------------------------------------------
// 5
// export const util = {
//     isEmpty(a) {
//         return !(a ??= undefined || length(trim(String(a))) > 0);
//     },
//     isNumber(a) {
//         return typeof a === "number" && a !== NaN;
//     }
// }

 

/* index.js */
//-----------------------------------------------
// 1. require (1) - CommonJS
// const counter = require("./counter.js")

// console.log(counter.count)
// counter.increase()
// console.log(counter.count)

//-----------------------------------------------
// 2. require (2) - CommonJS
// const counter = require("./counter.js")

// console.log(counter.isEmpty("") ? "empty" : "not empty");
// console.log(counter.isNumber(22) ? "number" : "not number");

//-----------------------------------------------
// 3. import (1)
// import {count, increase} from "./counter.js"

// console.log(count)
// increase()
// console.log(count)

//-----------------------------------------------
// 4.
import isCheck, {isEmpty, isNumber} from "./counter.js"
console.log(isEmpty("") ? "empty" : "not empty");
console.log(isNumber(22) ? "number" : "not number");
console.log(isCheck(22) ? "number" : "not number");

//-----------------------------------------------
// 5.
// import {util} from "./counter.js"
// console.log(util.isEmpty("") ? "empty" : "not empty");
// console.log(util.isNumber(22) ? "number" : "not number");

 

 

반응형