Beberapa Cara Menggunakan Fungsi di Javascript

mandaputtra

Manda Putra

Posted on November 21, 2019

Beberapa Cara Menggunakan Fungsi di Javascript

Hi! 馃槂 this is not right. Mungkin ini adalah beberapa cara kita membuat fungsi di JavaScript yang jarang kita gunakan dan saya harap beberapa contoh disini digunakan dengan tepat. Welcome to JavaScript function jungle!

Callback and Callback Promises

jangan dipakai yak, sekarang sudah jamannya promise. anda tidak mungkin juga kan bikin library lalu kasih tagline "still support callback"

Jikalau code snippet di bawah ini pernah terlintas di kepala kita, dan kita bertanya bagaimana sih caranya membuat yang seperti ini :

// then - cacth
mymodel.find({ name: 'Agus Sumboro' }).then(data => console.log(data)) // works

// async await
await mymodel.find({ name: 'Agus Sumboro' }) // works

// callback
mymodel.find({ name: 'Agus Sumboro' }, (data) => {
  console.log(data) // works also
})

// dan contoh lainnya
Enter fullscreen mode Exit fullscreen mode

yup, pertama kita harus pahami dulu bagaimana sih cara membuat callback, atau gampangnya sebuah function yang return valuenya adalah function :

function callback(params, cb) {
  cb(params)
}

callback('Halo Isabela', console.log) // Halo Isabela
Enter fullscreen mode Exit fullscreen mode

oke ini hanya support callback saja, lalu bagaimana jika ini support promise juga? saya sempat ingin membuat pull request di mongoose soal views karena menarik di sinilah saya tau kalau ternyata cara sebuah library menghandle ini cukup unik :

function cbPromises(params, callback) {
  const error = new Error(`${params} Not A Number`)
  // check if its function return callback if not return promise
  if (typeof callback === 'function') {
    if (isNaN(params)) return callback(null, error) // isNaN() not a number
    return callback(params)
  }
  return new Promise((resolve, reject) => {
    if(isNaN(params)) reject(error)
    resolve(params)
  })
}

//  now this works yay!
cbPromises('Halo', function(data, err) {
  if(err) return console.log(err.message) // Halo Not A Number
  console.log(data)
})

cbPromises(13)
  .then(data => console.log(data)) // 13
  .catch(err => console.log(err.message))
Enter fullscreen mode Exit fullscreen mode

Menurut saya agak naif menyuruh seorang 'newbie' (saya disini me-refer orang yang baru masuk ke dunia JS) menggunakan async await atau Promise tanpa memberinya kejelasan dahulu bagaimana cara kita membuat promise atau callback. Lest be clear here, and admit something... kita sendiri jarang membuat Promise apalagi Callback kalau di dunia front-end paling saya buat promise cuma untuk Loading Screen. At least we understand how it works and why promise and async is a thing not just syntatic sugar don't we? 馃榿.

Saya juga belum lama masuk ke dunia JS, mungkin 2 tahun kurang lebih. Saat saya pertama kali kerja (dan saat ini saya masih disana juga), salah satu proyek kantor saya adalah aplikasi dengan 300k++ loc (line of code). First commit program itu tercatat 2015 Januari, yaudah callback hell. hahaha. Biasanya program seperti ini di maintain 6 orang kalau di startup, dikarenakan resource minim cuma 2 orang 馃槀 yah satu cuti satu kena hajar callback.

Lanjut...

Recursive Function

Pernah ga ngalamin error seperti ini :

  • ERR: ENAMETOOLONG ternyata panjang nama sebuah file/argumen di terminal kita itu terbatas, lebih tepatnya dibatasi oleh OS.
  • warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.

Saya sering menemukan ini saat pertama belajar video processing, atau berkerja dengan child_process, mungkin penerapan function ini bisa membantu menyelesaikan masalah. Mungkin besok saya open ke github reponya setelah selesai bersih - bersih yang ga perlu, atau mungkin buat artikel soal video processing saja.

jika kamu mendapatkan error tsb hal yang dapat kamu lakukan melihat perintah terminal yang kamu gunakan, jika perintah terminal tersebut dapat di minimalisir maka mungkin looping adalah salah satu caranya

// recursive is fun
const arr = [1, 2, 4, 5]
let i = 0
function recursiveFun() {
  i++
  const element = arr[i]
  if(element === 4) return console.log(element)
  recursiveFun()
}
Enter fullscreen mode Exit fullscreen mode

Cara kerja function diatas sangat simple, ambil arr posisi ke i, kalau element bukan 4 maka i+1 panggil fungsi recursiveFun() lagi. Bagusnya function seperti ini dia menyimpan value variable yang ada diluarnya. Tentu ini sangat rare digunakan, dan saya sarankan tidak mengunakan ini kalu belum ketemu error seperti diatas yang mungkin saja solusinya adalah ini.

Salah satu code yang mungkin men-trigger error possible EventEmitter memory leak detected. :

let arr = [[1,2], [1,3]] // big two dimensional array

for (let i = 0; i < arr.length; i++) {
  const element = arr[i];
  supremeHardFunction(element)
}
Enter fullscreen mode Exit fullscreen mode

Jarang terjadi tapi mungkin anda alami, jangan sekali kali menambah eventListener kalau memang tidak perlu atau tidak bisa dihindari.

Closures Function

Saya yakin kalau ini sering banyak digunakan dan sangat saya sarankan digunakan. closures merupakan sebuah pattern untuk memberikan private access pada sebuah variable dalam sebuah function. Saya ambil contoh dari MDN saja.

function init() {
  var name = 'Mozilla'; // name merupakan local variable yang ada pada init
  function displayName() { // displayName() merupakan inner function, closures
    alert(name); // bisa menggunakan variable pada parent function
  }
  displayName();
}
init();
Enter fullscreen mode Exit fullscreen mode

Dan sebenarnya kita sering memakai ini, saya sering menggunakan ini saat memakai modul request atau mungkin fetch API. Seperti inilah bentuknya :

function api(key) {
  function get(url) {
    return fetch(`${url}?key=${key}`)
  }

  function post(url, params) {
    return fetch(url, {
      method: 'POST',
      body: JSON.stringify(params),
      headers: {
        'Authorization': `Bearer ${key}`
      }
    })
  }

  return { get, post }
}

const request = api('super-key-bruh!')
// oops kita dah ga perlu lagi masukin API key!
request.get('https://haloexample.com/getexample')
request.post('https://haloexample.com/postexample', { halo: 'Isabela' })
Enter fullscreen mode Exit fullscreen mode

Fluent Function / Methods Chaining

Sebenarnya saya agak lupa namanya Fluent Function/Waterfall Function banyak yang menyebut Methods Chaining. Tapi tentu sintak dibawah ini tidak asing.

const  = require('rambda.js)

//  not really a lamda function just example
位.chop([1, 2, 3, 1])
  .reduce(a => a + b)
  .toString()
Enter fullscreen mode Exit fullscreen mode

Yup, jika pernah terlintas bagaimana sih caranya membuat yang seperti itu. Untuk sesuatu yang simple ini saya memutuskan untuk menggunkan function saja, sebenarnya banyak library modern sekarang sudah menggunakan class.

// ini function tapi bisa disebut class...

const Person = function() {
  // define constructor
  this.name = 'Julia';
  this.shirt = 'blue';
  this.gender = 'female';
};

//  use prototype class function
Person.prototype.setName = function(name) {
  this.name = name;
  return this; // this adalah koenchi
};

Person.prototype.setShirt = function(shirt) {
  this.shirt = shirt;
  return this; // this adalah koenchi
};

Person.prototype.setGender = function(gender) {
  this.gender = gender;
  return this; // this adalah koenchi
};

Person.prototype.introduce = function() {
  const sheOrHe = this.gender === 'male' ? 'he' : 'she'
  console.log(`This is ${this.name}, ${sheOrHe} wear ${this.shirt} shirt`)

  return this; // this adalah koenchi
};
Enter fullscreen mode Exit fullscreen mode

Lalu dengan ini kita bisa gunakan snippet diatas secara indah :

const isabela = new Person()
  .setName('Isabela')
  .setShirt('red')
  .setGender('female')
  .introduce()

// atau

const wawan = new Person()
wawan.setName('Wawan')
wawan.setShirt('blue')
wawan.setGender('male')
wawan.introduce()
Enter fullscreen mode Exit fullscreen mode

Oke jika anda menggunakan code diatas tanpa return this.

const juni = new Person()
juni.setName('Juni').setGender('male')

const hey = new Person()
const juni = hey.setName('Juni')
juni.setGender('male')

// setGender is not a function
Enter fullscreen mode Exit fullscreen mode

ini dikarenakan setName sama sekali tidak me-return value, jadi saat setGender mau mengakses dia dapetnya undefined kasian. Jadi saat anda membuat function dan memanggil this pada saat return, ada kemungkinan anda mengembalikan nilai atau value di function tersebut.

馃檵: Lha kalau aku panggil `this` ini kok malah keluarnya dari instance framework?
馃惃: That's another story...
Enter fullscreen mode Exit fullscreen mode

Yak terimakasih telah membaca sampai akhir seperti biasa saya selalu open feedback, silahakan buat issue di repo blog ini atau mugkin mention saya di twitter.

Wrapping up! sebenarnya masih ada banyak sekali function pattern yang biasa dipakai pada JavaScript tapi tentunya tidak bisa saya cover semua karena saya juga masih baru di dunia JS/Node.js ini, hal diatas hanya beberapa pattern yang setidaknya pernah saya gunakan, semoga dapat membantu saat ingin membuat library di npm atau malah ingin berkontribusi ke beberapa library yang sudah ada. Thanks all and as usual have a nice day! 馃槃

Tips

Always name your function, dengan begitu kita tidak susah - susah saat profiling code kita jikalau memang nantinya perlu di profiling code-nya. Jika tidak tidak apa apa, karena memang jarang sekali kasus - kasus memory leak.

// dont do this :(
export const aUsualFunction = (params, params2) => { /** do stuff*/ }

// do this instead
export function aUsualFunction(params, paramas3) {
  // do stuff
}
Enter fullscreen mode Exit fullscreen mode
馃挅 馃挭 馃檯 馃毄
mandaputtra
Manda Putra

Posted on November 21, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related