TIL022_210414

keepcalmยท2021๋…„ 4์›” 15์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
22/33
post-thumbnail

๐ŸŠ ๊ฐ์ƒ

๐Ÿ“™ ์—ดํ’ˆํƒ€ ์ฝ”๋”ฉ ์‹œ๊ฐ„ 11hour
๐Ÿ‘๐Ÿผ -
๐Ÿ‘Ž๐Ÿผ -

๐Ÿš€ ๋ชฉํ‘œ

  • Udemy์—์„œ Javascript ๊ฐ•์ขŒ ์ˆ˜๊ฐ•ํ•˜๊ธฐ (332/682)
  • ์ปค๋ฐ‹ ์—ฐ์† 30์ผ ๋‹ฌ์„ฑํ•˜๊ธฐ (8/30, 4.14 ์™„๋ฃŒ)
  • ๋“œ๋ฆผ์ฝ”๋”ฉ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ธฐ์ดˆ ๊ฐ•์˜ ์™„๊ฐ• (12/23)
  • ~~๋ณต์Šต: TIL020 (์™„๋ฃŒ)~~

๐Ÿ“ฃ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ธฐ์ดˆ ๊ฐ•์˜: 09-13

โญ๏ธโญ๏ธโญ๏ธ Top 10 array function

join

api๊ฐ€ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ณ€ํ˜•์‹œํ‚ค๋Š” ,retentionํ•˜๋Š” api์ธ์ง€ ๋ณ€ํ˜•ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ
? : ์ „๋‹ฌํ•ด๋„ ๋˜๊ณ  ์ „๋‹ฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค (optional)
์›ํ•˜๋Š” ๊ตฌ๋ถ„์ž ์“ธ ์ˆ˜ ์žˆ์Œ

const arr2 = [1, 2];
console.log(arr2.indexOf[0]);

// Q1. make a string out of an array
{
  //๋‚ด ํ’€์ด
  const fruits = ['apple', 'banana', 'orange'];
  const stringFruits = fruits.toString();
  console.log(stringFruits);
  console.log(typeof stringFruits);
  
  //๋‹ต
  const result = fruits.join(',');
}

split

// Q2. make an array out of a string
{
  //๋‚ด ํ’€์ด
  //1
  const fruits = '๐ŸŽ, ๐Ÿฅ, ๐ŸŒ, ๐Ÿ’';
  const fruitArray = new Array();
  for (fruit of fruits) {
    fruitArray.push(fruit);
  }
  //, ๊นŒ์ง€ ๋ฐฐ์—ด๋กœ ๋“ค์–ด๊ฐ€๋ฒ„๋ฆฐ๋‹ค

  //2
  const fruits = '๐ŸŽ, ๐Ÿฅ, ๐ŸŒ, ๐Ÿ’';
  const fruitArray = new Array();
  fruitArray.push(fruits);
  //fruits.forEach ์‹œ๋„ํ•ด๋ดค์ง€๋งŒ fruits๊ฐ€ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์“ธ ์ˆ˜ ์—†๋‹ค
  //๊ทผ๋ฐ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ „์ฒด๊ฐ€ ์ธ๋ฑ์Šค0์ด ๋ผ๋ฒ„๋ฆผ
  //์›๋ž˜ ํ•˜๋‚˜์˜ string์ด๋ผ ๋‹ต์ด ๋งž๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ๊ณผ์ผ ๋„ค ๊ฐœ์˜ ์ŠคํŠธ๋ง์œผ๋กœ๋งŒ ๋œ ์–ด๋ ˆ์ด ๋งŒ๋“ค์–ด๋ณด๊ธฐ๋กœ ํ•จ

  //3
  const fruits = '๐ŸŽ, ๐Ÿฅ, ๐ŸŒ, ๐Ÿ’';
  const fruitArray = new Array();
  for (fruit of fruits) {
    fruitArray.push(fruit);
  }
  for (i = 0; i < fruitArray.length; i++) {
    if (fruitArray[i] === ',' || ' ') {
      fruitArray.splice(i, 1);
    }
  }
  //์•„... ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด index๊ฐ€ ๊ณ„์† ๋ณ€ํ•˜๋ฉด์„œ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์•ˆ ๋‚˜์˜ด/ ๋ฐ์ดํ„ฐ๊ฐ€ ์ด๋™ํ•จ

  //4
  //stackoverflow์— ๊ฒ€์ƒ‰ - string์ผ ๋•Œ ์—†์• ๋ณด๊ธฐ๋กœ ํ•จ
  const fruits = '๐ŸŽ, ๐Ÿฅ, ๐ŸŒ, ๐Ÿ’';
  const fruitArray = new Array();

  const newFruits = fruits.replace(/, /gi, '');
  //ig๋Š” i: ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์—†์ด g: ๋ฐœ์ƒํ•  ๋ชจ๋“  ํŒจํ„ด์— ๋Œ€ํ•ด ์ „์—ญ ๊ฒ€์ƒ‰์ด๋ž€ ๋œป
  console.log(newFruits);

  for (fruit of newFruits) {
    fruitArray.push(fruit);
  }
  console.log(fruitArray);

  //5
  //stackoverflow - ๋ฐฐ์—ด์ผ ๋•Œ ๊ฐ’์— ๋”ฐ๋ผ ์—†์• ๋ณธ๋‹ค๋ฉด?
  const fruits = '๐ŸŽ, ๐Ÿฅ, ๐ŸŒ, ๐Ÿ’';
  const fruitArray = new Array();
  for (fruit of fruits) {
    fruitArray.push(fruit);
  }
  //๋ฐฐ์—ด ๋งŒ๋“ค๊ณ , ,์™€ ๋ฐ์ดํ„ฐ๋กœ ํฌํ•จ๋œ ์ƒํƒœ
  function removeAllItem(arr, val) {
    let i = 0;
    while (i < arr.length) {
      if (arr[i] === val) {
        arr.splice(i, 1);
      } else {
        ++i;
      }
    }
    return arr;
  }
  removeAllItem(fruitArray, ' ');
  removeAllItem(fruitArray, ',');
  console.log(fruitArray);
  
  //๋‹ต
  const result = fruits.split(',');
}

reverse

// Q3. make this array look like this: [5, 4, 3, 2, 1]
{
  //๋‚ด ํ’€์ด
  const array = [1, 2, 3, 4, 5];
  array.reverse();
  //ํ†ต๊ณผ
}

๋ฐฐ์—ด ์ž์ฒด๋ฅผ ๋ณ€ํ™”์‹œํ‚จ๋‹ค. return ๊ฐ’๋„ ๋ณ€ํ•˜๊ณ  ์›๋ž˜ ๋ฐฐ์—ด๋„ ๋ณ€ํ•˜๊ณ 

slice

// Q4. make new array without the first two elements
{
  //๋‚ด ํ’€์ด
  const array = [1, 2, 3, 4, 5];
  array.splice(0, 2);
  console.log(array);
  
  //๋‹ต
  const result = array.splice(2, 5);
  console.log(array);
  console.log(result);
}

splice๋Š” ๋ฐฐ์—ด ์ž์ฒด์—์„œ ์‚ญ์ œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค
๋งˆ์ง€๋ง‰์€ ๋ฐฐ์ œ๋จ
slice๋Š” ๋ฐฐ์—ด์—์„œ ์›ํ•˜๋Š” ๋ถ€๋ถ„๋งŒ ๋ฆฌํ„ดํ•˜๊ณ  ์‹ถ์„ ๋•Œ

class Student {
  constructor(name, age, enrolled, score) {
    this.name = name;
    this.age = age;
    this.enrolled = enrolled;
    this.score = score;
  }
}
const students = [
  new Student('A', 29, true, 45),
  new Student('B', 28, false, 80),
  new Student('C', 30, true, 90),
  new Student('D', 40, false, 66),
  new Student('E', 18, true, 88),
];

find

// Q5. find a student with the score 90
{
  //๋‚ด ํ’€์ด
  const goodStudent = students.filter((a) => a.score === 90);
  console.log(goodStudent);
  
  //๋‹ต
  const result = students.find((student) => student.score === 90);
  console.log(result);
}

์ฒซ๋ฒˆ์งธ๋กœ ์‚ฌ๋ผ์ง„ ์š”์†Œ๋ฅผ ๋ฆฌํ„ด ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํŠธ๋ฃจ ๋ฆฌํ„ดํ•˜๋ฉด ๋ฐ”๋กœ ์š”์†Œ ๋ฆฌํ„ด
๋ฐฐ์—ด์— ๋“ค์–ด์žˆ๋Š” ์•„์ดํ…œ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœ
์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ด์„ ํŠธ๋ฃจ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋ฉˆ์ถ”๊ฒŒ ๋˜๊ณ  ํŠธ๋ฃจ๊ฐ€ ๋œ ์š”์†Œ๋ฅผ ๋ฆฌํ„ด

filter

// Q6. make an array of enrolled students
{
  //๋‚ด ํ’€์ด
  const enrollStudent = students.filter((a) => a.enrolled === true);
  console.log(enrollStudent);
  
  //๋‹ต
  const enrollStudent = students.filter((a) => a.enrolled);
}

map

// Q7. make an array containing only the students' scores
// result should be: [45, 80, 90, 66, 88]
{
  //๋‚ด ํ’€์ด
  const studentsScore = students.map((a) => a.score);
  console.log(studentsScore);
  
  //๋‹ต
  const studentsScore = students.map((student) => student.score);
}

๋ฐฐ์—ด ์•ˆ์— ๋“ค์–ด์žˆ๋Š” ์š”์†Œ ํ•œ ๊ฐ€์ง€ ํ•œ ๊ฐ€์ง€๋ฅผ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค.
์ง€์ •๋œ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ๊ฐ๊ฐ์˜ ์š”์†Œ๋ฅผ ํ•จ์ˆ˜๋ฅผ ๊ฑฐ์ณ์„œ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜
๋‹ค๋ฅธ ๋ฐฉ์‹์˜ ๋ฐ์ดํ„ฐ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ๋•Œ
์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ธ์ž ์˜๋ฏธ์—†์ด ์ง€์ •ํ•˜์ง€ ๋งˆ!

some

// Q8. check if there is a student with the score lower than 50
{
  //๋‚ด ํ’€์ด
  const studentsScore = students.map((a) => a.score);
  const lower50 = (e) => e < 50;
  console.log(studentsScore.some(lower50));
  
  //๋‹ต
  const result = studnets.some((student) => student.score < 50);
}

์ฝœ๋ฐฑํ•จ์ˆ˜ ๋ฆฌํ„ด์ด ํŠธ๋ฃจ๊ฐ€ ๋˜๋Š” ์• ๊ฐ€ ์žˆ๋‹ˆ? ํ•œ ๋ช…์ด๋ผ๋„ ์žˆ์œผ๋ฉด ํŠธ๋ฃจ ๋ฆฌํ„ด

every๋Š” ๋ชจ๋“  ์š”์†Œ๋“ค์ด ์กฐ๊ฑด์„ ์ถฉ์กฑํ•ด์•ผ ํŠธ๋ฃจ ๋ฆฌํ„ด

reduce

// Q9. compute students' average score
{
  //๋‚ด ํ’€์ด
  const studentsScore = students.map((a) => a.score);
  const reducer = (acc, cur) => acc + cur;
  const sum = studentsScore.reduce(reducer);
  const result = sum / studentsScore.length;
  console.log(result);
  
  //๋‹ต
  const result = students.reduce((prev, curr) => prev + curr.score, 0);
   console.log(result / students.length);
}

  //forEach ์‚ฌ์šฉ
  students.forEach((num) => {
  	result += num;
  });

๋ˆ„์ ๋œ ๊ฐ’ ์ „๋‹ฌ. ๋ฐฐ์—ด ํ•˜๋‚˜์”ฉ ์ˆœ์ฐจ์ ์œผ๋กœ curr์— ์ „๋‹ฌ
๋ฆฌํ„ดํ•˜๋Š” ๊ฐ’์ด ์ˆœ์ฐจ์ ์œผ๋กœ previous๋กœ ์ „๋‹ฌ
initial value 0์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Œ
์›ํ•˜๋Š” ์‹œ์ž‘์ ๋ถ€ํ„ฐ ๋ชจ๋“  ๋ฐฐ์—ด ๋Œ๋ฉด์„œ ๊ฐ’ ๋ˆ„์ ,
reduceRight์€ ๋ฐฐ์—ด์˜ ๋’ค์—์„œ๋ถ€ํ„ฐ ์‹œ์ž‘

//์„ฑ์ธ๋งŒ ์ „๋‹ฌํ•˜๊ธฐ
let result = userList.reduce((prev, cur) => {
	if (cur.age > 19) {
    	prev.push(cur.name);
    }
    return prev;
}, []);    

map + filter + join

// Q10. make a string containing all the scores
// result should be: '45, 80, 90, 66, 88'
{
  //๋‚ด ํ’€์ด
  const studentsScore = students.map((a) => a.score);
  studentsScore.toString();
  
  //๋‹ต
  const result = students
  	.map((student) => student.score)
    .filter((score) => score>= 50)
    .join();
}

map ๊ฐ™์€ api๋Š” ๋ฐฐ์—ด ์ž์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๊ธฐ์— ๋’ค์— ์ด์–ด์„œ ์“ธ ์ˆ˜ ์žˆ์Œ

sort

// Bonus! do Q10 sorted in ascending order
// result should be: '45, 66, 80, 88, 90'
{
  //๋‚ด ํ’€์ด
  scoreGrade = new Array();
  const studentsScore = students.map((a) => a.score);
  const reducer = (acc, cur, i) => {
    if (acc > cur) {
      scoreGrade.splice(i, 1).push(cur);
    } else {
      scoreGrade.splice(i, 1).push(acc);
    }
  };
  studentsScore.reduce(reducer);

  console.log(scoreGrade.toString());
  //๋ชปํ•˜๊ฒ ์–ด์—ฌ,,
  
  //๋‹ต
  const result = students
  	.map((student) => student.score)
    .sort((a, b) => a-b)
    .join();
}
  • ์ฐธ๊ณ ๋งํฌ: ์ฝ”๋”ฉ์•™๋งˆ
    Lodash ๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉํ•ด์„œ _.sortBy(arr); ํ†ตํ•ด ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ
    ์‹ค๋ฌด์—์„œ ๋กœ๋Œ€์‹œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ•™์Šตํ•  ๊ฒƒ

json

์„œ๋ฒ„ ํ†ต์‹ ์˜ ์‹œ์ž‘

http

hypertext transfer protocol

client -> server : request (์š”์ฒญ)
client <- server : response (์‘๋‹ต)

hypertext: ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์„œ ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ชจ๋‘ ํฌํ•จํ•ด์„œ ๋งํ•˜๋Š” ๊ฒƒ

ajax, xml, xhr

asynchronous javascript and xml
์›นํŽ˜์ด์ง€์—์„œ ๋™์ ์œผ๋กœ ์„œ๋ฒ„์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ 

xhr : xmlhttprequest - ์˜ค๋ธŒ์ ํŠธ(๋ธŒ๋ผ์šฐ์ € api ์ค‘ ํ•˜๋‚˜๋กœ ์ด api๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ์„œ๋ฒ„์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค)
fetch() API - ์ตœ๊ทผ ๋ธŒ๋ผ์šฐ์ €์— ์ถ”๊ฐ€๋œ api (์ต์Šคํ”Œ๋กœ๋Ÿฌ์—์„œ ์•ˆ ๋จ๐Ÿ˜‚)

xml: html๊ฐ™์€ ๋งˆํฌ์—… ์–ธ์–ด ์ค‘ ํ•˜๋‚˜ -> ๊ฐ€๋…์„ฑ ๋ถˆํŽธ, ํŒŒ์ผ ์‚ฌ์ด์ฆˆ ๋น„๋Œ€ํ•ด์„œ ๋งŽ์ด ์‚ฌ์šฉ ์•ˆ ํ•จ
์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•œ ํŒŒ์ผ ํฌ๋งท ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ -> xml๋งŒ ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์•„๋‹˜, xhr ์— ํ”๋“ค๋ฆฌ์ง€ ์•Š์•„๋„ ๋จ, ์™ธ๋ถ€๋กœ ๊ฐ€๋Š” api ๋งŒ๋“ค ๋•Œ ์ด๋ฆ„ ๋ช…๋ฃŒํ•˜๊ฒŒ ์ง“๊ธฐ

json

json: javascript object notation
data format / ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์˜ค๋ธŒ์ ํŠธ์ฒ˜๋Ÿผ ํ‚ค์™€ ๋ฐธ๋ฅ˜๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค
๋ชจ๋ฐ”์ผ์—์„œ๋„ ๊ฐ€๋Šฅ,

object -> json(string) : serialize ์ง๋ ฌํ™”
object <- json(string) : deserialize

object to json

stringfy(obj)

  • ์˜ค๋ฒ„๋กœ๋”ฉ: ํ•จ์ˆ˜์˜ ์ด๋ฆ„์€ ๋™์ผํ•˜์ง€๋งŒ ์–ด๋–ค ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ๊ฒƒ
let json = JSON.stringfy(true);
console.log(json);

json = JSON.stringfy(['api','banana']);
console.log(json);

const rabbit = {
	name: 'tori',
    color : 'white',
    size: null,
    birthDate : new Date(),
    symbol: Symbol("id"),
    jump: function () {
    	console.log(`${this.name} can jump`);
	},
};    

json = JSON.stringfy(rabbit);
console.log(json);
//์ ํ”„๋ผ๋Š” ํ•จ์ˆ˜๋Š” json์— ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค, ์˜ค๋ธŒ์ ํŠธ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— 
//symbol ๋˜ํ•œ ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค

json = JSON.stringfy(rabbit, ['name']);
console.log(json);
//์ด๋ฆ„๋งŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค - ์›ํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๋งŒ ๊ณจ๋ผ์„œ ์ „๋‹ฌ 

json = JSON.stringfy(rabbit, (key, value) =>{
  console.log(`key:${key}, value: ${value}`);
  return key === 'name' ? 'ellie': value;
});
console.log(json);
//์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ด์šฉํ•ด์„œ ์„ธ๋ฐ€ํ•˜๊ฒŒ ํ†ต์ œ

json to object

parse(json)

const obj = JSON.parse(json);
console.log(obj);
rabbit.jump();
//parse ๋œ obj ์—๋Š” jump functioin ์—†๋‹ค - deserialize ๋๊ธฐ ๋•Œ๋ฌธ
obj.jump() //error

console.log(rabbit.birthDate.getDate()); //์–˜๋Š” ๋˜๋Š”๋ฐ date๋ผ๋Š” ์˜ค๋ธŒ์ ํŠธ ์ž์ฒด๋ผ์„œ
console.log(obj.birthDate.getDate()); //์–˜๋Š” ์—๋Ÿฌ  string ํ˜•ํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์—

const obj = JSON.parse(json, (key, value) => {
  console.log(`key:${key}, value: ${value}`);
  return key === 'birthDate' ? Date(value) : value;
});
console.log(obj.birthDate.getDate()); //์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ผ์š” ^^

MDN
JavaScript.info
JavaScript.info ํ•œ๊ตญ์–ด

์œ ์šฉํ•œ ์‚ฌ์ดํŠธ:
JSON Diff checker
JSON Beautifier/editor
JSON Parser
JSON Validator

javascript callback

๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ - callback ์ง€์˜ฅ๊ณผ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ

javascript is synchronous
execute the code block by order after hoisting
hoisting: var, function declaration

๋ธŒ๋ผ์šฐ์ € api๋Š” ๋ธŒ๋ผ์šฐ์ €์— ์š”์ฒญํ•œ ๋’ค ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ๋ผ์ธ ์‹คํ–‰
์ง€๊ธˆ ์ง€์ •ํ•œ ํ•จ์ˆ˜๋ฅผ ๋‚˜์ค‘์— ๋‹ค์‹œ ๋ถˆ๋Ÿฌ๋‹ฌ๋ผ - callback function

์ฝœ๋ฐฑ์—๋„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค
//sychronous callback
//asynchronous callback

//์ฝœ๋ฐฑ ์ง€์˜ฅ ์ฒดํ—˜ํ•˜๊ธฐ
class UserStorage {
  //UserStorage์—๋Š” ๋‘ ๊ฐ€์ง€ api๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž
  loginUser(id, password, onSuccess, onError) {
    setTimeout(() => {
      if (
        (id === 'ellie' && password === 'dream') ||
        (id === 'coder' && password === 'academy')
      ) {
        onSuccess(id);
      } else {
        onError(new Error('not found'));
      }
    }, 2000);
  }
  //์›๋ž˜๋Š” ๋กœ๊ทธ์ธํ•˜๋Š” ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ํ•œ๋ฒˆ์— ๋ฐฑ์—”๋“œ์—์„œ ๋ฐ›์•„์˜ค์ง€๋งŒ ์ด๋ฒˆ๋งŒ ์ด๋ ‡๊ฒŒ ๊ฐ€์ •
  getRoles(user, onSuccess, onError) {
    setTimeout(() => {
      if (user === 'ellie') {
        onSuccess({ name: 'ellie', role: 'admin' });
      } else {
        onError(new Error('no access'));
      }
    }, 1000);
  }
}  

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your passrod');
userStorage.loginUser(
  id,
  password,
  user => {
    userStorage.getRoles(
      user,
      userWithRole => {
        alert(
          `Hello ${userWithRole.name}, you have a ${userWithRole.role} role`
        );
      },
      error => {
        console.log(error);
      }
    );
  },
  error => {
    console.log(error);
  }
);

javascript Promise

๋น„๋™๊ธฐ ๊ฐ„ํŽธ ์ฒ˜๋ฆฌ ๋„์™€์ฃผ๋Š” ์˜ค๋ธŒ์ ํŠธ
์ •์ƒ์ ์œผ๋กœ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ’ ์ „๋‹ฌ, ์•„๋‹ˆ๋ผ๋ฉด ์—๋Ÿฌ ์ „๋‹ฌ

promise is a javascript object for asynchronous operation

  1. state : ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฒ˜๋ฆฌ ์ค‘์ธ์ง€, ์„ฑ๊ณต์ธ์ง€, ์‹คํŒจ์ธ์ง€ ์ดํ•ดํ•˜๊ธฐ
  2. producer ์™€ consumer : ๋‘˜์˜ ์ฐจ์ด์  ์•Œ๊ธฐ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ œ๊ณต/ ์ œ๊ณต๋œ ๋ฐ์ดํ„ฐ ์“ฐ๋Š” ์‚ฌ๋žŒ

state : pending(์˜คํผ๋ ˆ์ด์…˜ ์ˆ˜ํ–‰์ค‘) -> fulfilled or rejected

Producer

Promise๋Š” class, ์ƒ์„ฑ์ž์ด๊ธฐ ๋•Œ๋ฌธ์— new๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
Promise ์ƒ์„ฑ์ž์— executor๋ผ๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•ด์ค˜์•ผ ํ•œ๋‹ค.
์ด executor ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๋˜ ๋‘ ๊ฐ€์ง€ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌ ๋ฐ›๋Š”๋‹ค.
๋ฐ”๋กœ resolve, reject
promise๋ฅผ ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„ ์šฐ๋ฆฌ๊ฐ€ ์ „๋‹ฌํ•œ executor๋ผ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋ฐ”๋กœ ์‹คํ–‰๋œ๋‹ค
๋”ฐ๋ผ์„œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ์‚ฌ์šฉ์ž๊ฐ€ ์š”๊ตฌํ–ˆ์„ ๋•Œ๋งŒ ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ์ด ์‚ฌ์‹ค์„ ๊ฐ„๊ณผํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ํ•˜๊ฒŒ ๋œ๋‹ค.
when new Promise is created, the executor runs automatically.

//2์ดˆ ์ •๋„ ์ผํ•˜๋‹ค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌ๋˜๋ฉด ellie๋ผ๋Š” ๊ฐ’์„ resolve callback ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ๋‹ค
const promise = new Promise((resolve, reject) => {
  //doing some heavy work (network, read files)
  console.log('doing something...');
  setTimeout(() => {
    resolve('ellie');
    //reject(new Error('no network'))
    //reject๋Š” Error๋ผ๋Š” ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ’์„ ์ „๋‹ฌํ•œ๋‹ค 
    //Error๋ผ๋Š” ํด๋ž˜์Šค๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ ์ค‘์˜ ํ•˜๋‚˜์ด๋‹ค 
    //then์œผ๋กœ ์„ฑ๊ณต์ ์ธ ์ผ€์ด์Šค๋งŒ ๋‹ค๋ฃจ๋ฉด uncaugth ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค 
  }, 2000);
});

Consumer

then, catch, finally
promise ๊ฐ€ ์ž˜ ๋˜๋ฉด then, ๊ฐ’์„ ๋ฐ›์•„์™€์„œ ์›ํ•˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ๋‹ค
์—ฌ๊ธฐ์„œ value๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋Š”, ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ˆ˜ํ–‰๋ผ์„œ resolve ์ฝœ๋ฐฑํ•จ์ˆ˜์—์„œ ์ „๋‹ฌ๋œ 'ellie'๋ผ๋Š” ๊ฐ’

์ฒด์ด๋‹: ๋ฆฌํ„ด๋œ ์–ด๋ ˆ์ด์— ํ•จ์ˆ˜ ํ˜ธ์ถœ - ๋ฆฌํ„ด - ํ˜ธ์ถœ
then ํ˜ธ์ถœํ•˜๋ฉด promise ๊ฐ€ ๋ฆฌํ„ด์ด ๋˜๊ณ , ๋ฆฌํ„ด๋œ ํ”„๋กœ๋ฏธ์Šค์— ์บ์น˜๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ

promise //
  .then((value) => {
  console.log(value);
})
  .catch(error => {
    console.log(error); //Error: no network
})
  .finally(() => { //์„ฑ๊ณต ์‹คํŒจ์™€ ์ƒ๊ด€์—†์ด ๋ฌด์กฐ๊ฑด ๋งˆ์ง€๋ง‰์— ํ˜ธ์ถœ๋œ๋‹ค
    console.log('finally');
});

promise chaining

const fetchNumber = Promise((resolve, reject) => {
  setTimeout(() => resolve(1), 1000);
});

fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
//๋‹ค๋ฅธ ์„œ๋ฒ„์—์„œ ๋ณด๋‚ด์„œ ๋‹ค๋ฅธ ์ˆซ์ž๋กœ ๋ณ€ํ™˜๋œ ๊ฐ’ ๋ฐ›์•„์˜ค๊ธฐ
//then์—์„œ๋Š” ๊ฐ’์„ ์ „๋‹ฌํ•ด๋„ ๋˜๊ณ  ๋˜ ๋‹ค๋ฅธ ๋น„๋™๊ธฐ์ธ promise๋ฅผ ์ „๋‹ฌํ•ด๋„ ๋œ๋‹ค 
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num -1), 1000);
  });
})
.then(num => console.log(num)); //5 

error handling

const getHen = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve('๐Ÿ“'),1000);
  });
const getEgg = hen =>
  new Promise((resolve, reject) => {
    //setTimeout(() => resolve(`${hen} => ๐Ÿฅš`),1000);
    setTimeout(() => reject(new Error(`error! ${hen} => ๐Ÿฅš`)),1000);
  });
const cook = egg =>
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => ๐Ÿณ`),1000);
  });
  
//1
getHen()
  .then(hen => getEgg(hen))
  .then(egg => cook(egg))
  .then(meal => console.log(meal));
  
//๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์“ฐ๊ธฐ - ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ „๋‹ฌํ•  ๋•Œ ๋ฐ›์•„์˜ค๋Š” ๋ฐธ๋ฅ˜๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ๋ฐ”๋กœ ํ•˜๋‚˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ƒ๋žต ๊ฐ€๋Šฅ
getHen() //
  .then(getEgg)
  .catch(error => {
    return '๐Ÿฅจ';
  })
  //๋‹ฌ๊ฑ€ ๋ฐ›์•„์˜ฌ ๋•Œ ์—๋Ÿฌ ์ƒ๊ธฐ๋ฉด ๋นต์„ ๋Œ€์‹  ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์—๋Ÿฌ ํ•ธ๋“ค๋ง 
  //์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์€ ์—๋Ÿฌ ๋’ค์— ๋ฐ”๋กœ catch ์ž‘์„ฑํ•˜๋ฉด ๋จ 
  //๐Ÿฅจ => ๐Ÿณ
  .then(cook)
  .then(console.log);
  .catch(console.log);
//catch ์ž‘์„ฑํ•จ์œผ๋กœ์จ ์—๋Ÿฌ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ์Œ 

callback hell promise๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ

//์ฝœ๋ฐฑ ์ง€์˜ฅ ์ฒดํ—˜ํ•˜๊ธฐ
class UserStorage {
  //UserStorage์—๋Š” ๋‘ ๊ฐ€์ง€ api๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž
  loginUser(id, password) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (
          (id === 'ellie' && password === 'dream') ||
          (id === 'coder' && password === 'academy')
        ) {
          resolve(id);
        } else {
          reject(new Error('not found'));
        }
      }, 2000);
    }
  getRoles(user) {
    return new  Promise((resolve, reject) => {
      setTimeout(() => {
        if (user === 'ellie') {
          resolve({ name: 'ellie', role: 'admin' });
        } else {
          reject(new Error('no access'));
        }
      }, 1000);
    }
  }  

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your passrod');
userStorage
  .loginUser(id,password)
  .then(userStorage.getRoles)
  .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`);
  .catch(console.log);

async & await

promise๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ„ํŽธํ•˜๊ณ  ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•ด์ค€๋‹ค
ํ”„๋กœ๋ฏธ์Šค ์ฒด์ด๋‹์„ ๊ณ„์† ํ•˜๊ฒŒ ๋˜๋ฉด ์ฝ”๋“œ ๋‚œ์žกํ•ด์ง€๋Š”๋ฐ ๊ทธ๊ฑธ ๋™๊ธฐ์‹์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Œ

๊ธฐ์กด์— ์กด์žฌํ•˜๋Š” ํ”„๋กœ๋ฏธ์Šค์— ๊ฐ„ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š”, ๊ฐ„ํŽธํ•œ api๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ
-> syntactic sugar
-> ์˜ˆ๋กœ ํด๋ž˜์Šค๊ฐ€ ์žˆ์Œ, ์Šคํฌ๋ฆฝํŠธ์—์„œ ํด๋ž˜์Šค๋Š” ์ƒˆ๋กœ์šด ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฒ ์ด์Šค๋กœ ํ•œ ์œ„์— ์‚ด์ง ๋ง ๋ถ™์—ฌ์ง„ ๊ทธ๋Ÿด์‹ธํ•œ syntactic sugar

clear style of using promise ;) // ๊ทธ๋ ‡๋‹ค๊ณ  ๋ฌด์กฐ๊ฑด ํ”„๋กœ๋ฏธ์Šค ๋‚˜์œ ๊ฒŒ ์•„๋‹ˆ๋ผ ์„œ๋กœ ๋งž๋Š” ๊ฒŒ ์žˆ์Œ

async

//promise 
function fetchUser() {
  reurn new Promise ((resolve, reject) => {
    //do network request in 10 secs
    resolve('ellie');
  });
}
//async ์ž๋™์ ์œผ๋กœ ํ•จ์ˆ˜ ์•ˆ์— ์žˆ๋Š” ๋ธ”๋ก๋“ค์ด promise๋กœ ๋ณ€ํ™˜์ด ๋œ๋‹ค
async function fetchUser() {
    //do network request in 10 secs
    return 'ellie';
}

await

await๋Š” async ์•ˆ์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ์Œ
await๋Š” ๋”œ๋ ˆ์ด๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์ค€๋‹ค

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
  await delay(2000);
  return '๐ŸŽ';
}

async function getBanana() {
  await delay(1000);
  return '๐ŸŒ';
}

//promise ์“ฐ๋ฉด, ์ค‘์ฒฉ์  ์ฒด์ด๋‹ํ•˜๋ฉด ์ฝœ๋ฐฑ ์ง€์˜ฅ๊ณผ ๋น„์Šทํ•œ ๋ฌธ์ œ ๋ฐœ์ƒ
function pickFruits() {
  return getApple()
  .then(apple => {
    return getBanana()
    .then(banana => `${apple} + ${banana}`)
  })
}
pickFruits().then(console.log);

//๋‹ค์Œ์€ async๋ฅผ ์“ด ๊ฒƒ
async function pickFruits() {
    const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`;
}
//try cath๋กœ ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๊ฐ€๋Šฅ

pickFruits().then(console.log);

//๊ทผ๋ฐ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ๊ณผ 1์ดˆ ๋ฐ”๋‚˜๋‚˜ 1์ดˆ ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜์ž–์•„,,,
//promise ๋งŒ๋“ค๋ฉด ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ ํ™œ์šฉํ•˜์ž
//๋ณ‘๋ ฌ์  ์‹คํ–‰๊ฐ€๋Šฅ
async function pickFruits() {
	const applePromise = getApple();
    const bananaPromise = getBanana();
    const apple = await applePromise;
    const banana = await bananaPromise;
    return `${apple} + ${banana}`;
}

//๊ทผ๋ฐ ์ด๋ ‡๊ฒŒ ์„œ๋กœ ์ƒ๊ด€์—…์–ด์„œ ๋ณ‘๋ ฌ์  ์‹คํ–‰ ๊ฐ€๋Šฅํ•  ๋•Œ ๋” ๊นจ๋—ํ•˜๊ฒŒ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๋Š” promise api๊ฐ€ ์žˆ๋‹ค?
//๋ณ‘๋ ฌ์ ์œผ๋กœ ๋‹ค ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ๋ชจ์•„์ค€๋‹ค. 

Promise.all

function pickAllFruits() {
  return Promise.all([getApple(), getBanana()]).then(fruits =>
    fruits.join(' + ')
  );
}
pickAllFruits().then(console.log);

Promise.race

//๋‚˜๋Š” ๊ฐ€์žฅ ๋จผ์ € ๋”ฐ์ง€๋Š” ํ•˜๋‚˜๋งŒ ๊ฐ–๊ณ  ์‹ถ์–ด ํ•  ๋•Œ๋Š”
function pickOnlyOne() {
  return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);

Homework

//๊ทธ๋Ÿผ ์ด ๋ถ€๋ถ„ ์–ด๋–ป๊ฒŒ await ํ™œ์šฉํ•ด์„œ ์“ธ ์ˆ˜ ์žˆ์„๊นŒ?
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your passrod');
userStorage
  .loginUser(id,password)
  .then(userStorage.getRoles)
  .then(user => alert(`Hello ${user.name}, you have a ${user.role} role`);
  .catch(console.log);

0๊ฐœ์˜ ๋Œ“๊ธ€