Hatalarınızı Kontrol Etmek İçin En İyi Uygulamalar – JSManifest

Hatalarınızı Kontrol Etmek İçin En İyi Uygulamalar – JSManifest

Kodunuzu yazarken hataların oluşabileceği farklı senaryoları göz önünde bulundurmak önemlidir. Web uygulamanızın ayrılmaz bir parçası olurlar, çünkü ele alınmadan bırakılırsa kaçınılamayan ölümcül senaryolardan (uygulamanızın tamamen çökmesi gibi) kaçınabilirsiniz.

Bu gönderi, hataları kontrol etme ve bunları JavaScript’te işleme konusunda bazı en iyi uygulamaları gözden geçirecektir.

Hatayı Genişletme

Hata işleyicileriniz içinde daha açıklayıcı bir hata sağlamak genellikle yararlıdır. Ve bununla sadece hata mesajınızı daha net yazmaktan bahsetmiyorum. Bahsettiğim şey uzatmak Error sınıf.

Bunu yaparak özelleştirebilirsiniz name ve message hata ayıklama ve buna ihtiyaç duyan özel alıcılar, ayarlayıcılar ve yöntemler eklemek için yararlı olacak özellik:

class BadParametersError extends Error {
  name = 'BadParametersError'

  constructor(message) {
    super(message)
  }

  get recommendation() {
    return this._recommendation
  }

  set recommendation(recommendation) {
    this._recommendation = recommendation
  }
}

Bu, özellikle benzer şekilde atan birden çok kod bloğunuz varsa, daha sorunsuz bir hata ayıklama deneyimi sağlayabilir. Kodunuzdaki birden çok senaryo aynı nedenlerle oluşturulduğunda ve bazı ek bağlamlara ihtiyaç duyduğunda, geri dönüp tam olarak neden bir yardımcı program olmadan atıldığını bulmak biraz zor olabilir – hatanın türüne bağlı olarak elbette.

Bunun yararlı hale geldiği bir senaryoyu gözden geçirelim.

Diyelim ki çözümleyici işlevlerin bir listesini alan bir işleviniz var. İşlev bir argüman alır ve çalıştığında çözümleyiciler arasında döngü yapar ve argümanı her işleve iletir. Bir işlev bir sonuç döndürürse, döngüyü durdurur ve sonucu döndürür:



function composeResolvers(...resolvers) {
  return (args) => {
    let result

    for (let index = 0; index < resolvers.length; index++) {
      const resolve = resolvers[index]
      result = resolve(args)
      if (result) {
        break 
      }
    }

    return result
  }
}

Şimdi, kullanıcıyı yaşlarına göre bir gruba atamadan önce doğduğu yılı girmesini isteyen bir sayfa oluşturduğumuzu varsayalım:

import composeResolvers from '../composeResolvers'

const resolvers = []

const someResolverFn = (userInput) => {
  if (userInput > 2002) {
    return 'NewKidsOnTheBlock'
  }
  return 'OldEnoughToVote'
}


if (/chrome/i.test(navigator.userAgent)) {
  resolvers.push(someResolverFn)
}

const resolve = composeResolvers(...resolvers)

window.addEventListener('load', () => {
  const userInput = window.prompt('What year was your computer created?')
  const result = resolve(userInput)
  window.alert(`We recommend that you register for the group: ${result}`)
})

Bu kod kullanıcıya sorar ve tıkladıklarında TAMAMyaşları atanır userInput ve tarafından üretilen işleve bir argüman olarak gönderilir. composeResolvers:

Ve bittiğinde çalışır window.alert kullanıcıya hesaplanan grubu göstermek için:

javascript2'de pencere uyarısı sonucu

Bu iyi çalışıyor ama ya kullanıcı değildi chrome tarayıcıyı mı kullanıyorsunuz? Bu, bu satırın çalışmayacağı anlamına gelir:

resolvers.push(someResolverFn)

Bu, utanç verici beklenmeyen bir sonuç üretir:

pencere istemi beklenmedik tanımsız sonuç

Bu gibi işlenmemiş hataların önüne bir normal atarak önleyebiliriz. Error veya daha spesifik olanı kullanabiliriz BadParametersError:



function composeResolvers(...resolvers) {
  if (!resolvers.length) {
    const err = new BadParametersError(
      'Need at least one function to compose resolvers',
    )
    err.recommendation =
      'Provide a function that takes one argument and returns a value'
    throw err
  }
  return (args) => {
    let result

    for (let index = 0; index < resolvers.length; index++) {
      const resolve = resolvers[index]
      result = resolve(args)
      if (result) {
        break 
      }
    }

    return result
  }
}

Bu şekilde, bu hatanın kullanıcıya ulaşma şansı çok daha düşüktür ve geliştiricinin hatayı düzeltmesini sağlar:

javascript'te atılan-hata-sonuç-kötü-parametreler

Birden çok işlev bu stratejiyi kullanıyorsa ve aşağıdaki gibi bir özellik eklenmişse recommended örneğin, hata ayıklama deneyimi çok daha kolay hale gelir.

Şimdi daha iyi bir savunma mekanizması olan böyle bir şeye yazılabilir:

const resolve = composeResolvers(...resolvers)

window.addEventListener('load', () => {
  const userInput = window.prompt('What year was your computer brought to you?')
  let result

  try {
    result = resolve(userInput)
  } catch (error) {
    if (error instanceof BadParametersError) {
      console.error(
        `[Error] ${error.message}. Here's a recommendation: ${error.recommendation}`,
      )
      console.log(error.recommendation)
    } else {
      
      return window.alert(
        'We are sorry, there was a technical problem. Please come back later',
      )
    }
  }

  window.alert(`We recommend that you register for the group: ${result}`)
})

Kullanın TypeError

Hataları genellikle fırlatarak hallederiz Error. Ancak, fırsat geldiğinde senaryoyu daraltmak için yerleşik JavaScript hataları mevcut olduğunda, sadece onları kullan:

async function fetchDogs(id) {
  let result
  if (typeof id === 'string') {
    result = await api.fetchDogs(id)
  } else if (typeof id === 'array') {
    result = await Promise.all(id.map((str) => api.fetchDogs(id)))
  } else {
    throw new TypeError(
      'callSomeApi only accepts a string or an array of strings',
    )
  }
  return result
}

const params = { id: 'doggie123' }

let dogs

fetchDogs(params)
  .then((dogs) => {
    dogs = dogs
  })
  .catch((err) => {
    if (err instanceof TypeError) {
      dogs = Promise.resolve(fetchDogs(params.id))
    } else {
      throw err
    }
  })

Test yapmak

türetilmiş yararlanarak Errors testleri, iddialarınızı yapmak için bunları doğrudan kullanabildiğiniz için daha sağlam hale gelir:

import { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import fetchCats from '../fetchCats'

chai.use(chaiAsPromised)

it('should only take in arrays', () => {
  expect(fetchCats('abc123')).to.eventually.rejectWith(TypeError)
})

Aşırıya kaçmak

Ne kadar yararlı olduğunu bilmek, özellikle JavaScript’i yeni öğrenmeye başladığınızda, aklınıza gelebilecek her olası senaryo için bir sürü özel hata oluşturmak da cazip hale geliyor. Bu nedenle, küçük ila orta ölçekli bir uygulamanız varsa ve aşağıdaki gibi bir durumla karşılaşırsanız:

class AbortExecuteError extends Error {
  name = 'AbortExecuteError'

  constructor(message) {
    super(message)
  }
}

class BadParameters extends Error {
  name = 'BadParameters'

  constructor(message) {
    super(message)
  }
}

class TimedOutError extends Error {
  name = 'TimedOutError'

  constructor(message) {
    super(message)
  }
}

class ArrayTooLongError extends Error {
  name = 'ArrayTooLongError'

  constructor(message) {
    super(message)
  }
}

class UsernameError extends Error {
  name = 'UsernameError'

  constructor(message) {
    super(message)
  }
}

O zaman bu yaklaşımı yeniden düşünebilir ve Gerçekten bunu yapmak gerek ya da yapmamak. Çoğu zaman daha net bir hata sağlamak için yeterlidir message. Özel hatalarla ilgili iddialarda bulunmak, yalnızca bir jeton örneğin zaman aşımına uğramış bir isteği yeniden denemek için:

class TimedOutError extends Error {
  name = 'TimedOutError'
  retried = 0

  constructor(message) {
    super(message)
  }

  set retry(callback) {
    this._retry = callback
  }

  retry(...args) {
    this.retried++
    return this._retry(...args)
  }
}

class ConnectToRoomTimedOutError extends TimedOutError {
  name = 'ConnectToRoomTimedOutError'

  constructor(message) {
    super(message)
  }

  get token() {
    return this._token
  }

  set token(token) {
    this._token = token
  }
}

let timeoutRef

async function connect(token) {
  if (timeoutRef) clearTimeout(timeoutRef)
    timeoutRef = setTimeout(() => {
      const err = new ConnectToRoomTimedOutError(
        'Did not receive a response from the server',
      )
      err.retry = connect
      err.token = token
      throw err
    }, 10000)
    const room = await api.join(token)
    clearTimeout(timeoutRef)
    return room
  }
}

const joinRoom = () => getToken().then((token) => connect(token))

async function start() {
  try {
    let room = await joinRoom()
    return room
  } catch (err) {
    if (err instanceof ConnectToRoomTimedOutError) {
      try {
        
        room = await err.retry(err.token)
        return room
      } catch (innerErr) {
        throw innerError
      }
    }
    throw err
  }
}

start()
  .then((room) => {
    console.log(`Received room, oh yea!`, room)
  })
  .catch(console.error)

Çözüm

Hatalarınızı kontrol etmek, uygulamanız üzerinde kontrol sağlar. Ayrıca zamandan ve paradan tasarruf etmenizi sağlar. Bu, bu yazının sonunu tamamlıyor! Umarım bunu değerli bulmuşsunuzdur ve gelecekte daha fazlasını ararsınız!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.