Usuwanie callbacków

0

Chciałbym przerobić pewien kod napisany w js. Niestety w kodzie jest zagnieżdżonych wiele funkcji (callbacków). Jak to najlepiej uporządkować? Przykład:

database.read("value", function (result) {
process(result.text, function(success) {
if (success)
console.log("OK");
}
}

Funkcja database.read jest asynchroniczna. Chciałbym to przerobić na taki kod jednocześnie zachowując asynchroniczny charakter funkcji, tak aby odwołanie do bazy danych nie blokowało programu:

var result = database.read("value");
var success = process(result.text);
if (success)
console.log("OK");

0

Nie zrobisz tego tak jak chcesz to zrobić, bo jak sam napisałeś, odwołanie się do ```
database

Tak jak @Pixello napisał- promise ale nadal będziesz zagnieżdżać funkcje. Ucieczką może być zamykanie ciał callbacków w funkcje i umieszczanie ich w innym miejscu dla zwiększenia czytelności.
Jeżeli jest to ES6 i ```database.read``` jest oznaczone jako ```async``` możesz użyć ```await``` chociaż to raczej słaby pomysł bo nie wiadomo jak długo będzie czekać.
0
Piotr Poźniak napisał(a):

Tak jak @Pixello napisał- promise ale nadal będziesz zagnieżdżać funkcje.

No właśnie nie, promisy są po to by można było łatwo spłaszczyć tą strukturę.

Jeżeli jest to ES6 i database.read jest oznaczone jako async możesz użyć await chociaż to raczej słaby pomysł bo nie wiadomo jak długo będzie czekać.

?? A czy Ty wiesz w ogóle jak działa async-await? Co tam będzie długo czekać?

BTW async-await nie jest częścią ES6 (ani ES7)

1

Ale kombinujecie. Przypisz callbacki do zmiennych.

1

@Piotr Poźniak @Uczynny Kot

Wersja z promise:

function doStuff () {
  database
    .read('value')
    .then(result => process(result.text))
    .then(success => {
      if (success) {
        console.log('OK')
      }
    })
}

doStuff()

CodePen: https://codepen.io/caderek/pen/OOpRPJ?editors=0012

Wersja z async-await:

async function doStuff () {
  const result = await database.read('value')
  const success = await process(result)
  
  if (result) {
    console.log('ok')
  }
}

doStuff()

CodePen: https://codepen.io/caderek/pen/MOpjev?editors=0012

Jak widać nie ma zagnieżdżeń i nic na nic nie czeka w przypadku async-await bardziej niż w wersji z callbackami i promisami (patrz kolejność wykonania console.log na CodePenie).
database.read jak widać wcale nie musi być oznaczone jako async - wystarczy, że zwróci promise (nawet jak nie zwraca i nie możesz jej przerobić to łatwo ją w promisa opakować).

Tłumaczyć jak async-await działa raczej nie będę, bo te informacje można ławo wyszukać.

A co do przykładu użytkownika @Piotr Poźniak - jest zagnieżdzony głównie ze względu na korzystanie z domknięć, możnaby go spłaszczyć przekazując dane w parametrach - czy będzie to czytelniejsze cięzko powiedzieć. Bez lepszego przeanalizowania ciężko też powiedzieć, czy rozwiązanie jest w ogóle optymalne. W każdym razie nie wiem czego ten przykład ma dowodzić ;)

@Bogaty Kret
Jasne, można po prostu przypisać callbacki do zmiennych, ale kod nadal będzie mniej czytelny, rozlazły i trzeba będzie wymyślać dodatkowe nazwy zmiennych (to akurat mniejszy problem, bo ogólnie nazwane funkcje często są wskazane, choć czasem jest to sztuczny szum jak callback jest prosty). Dlatego promisy i async-await to nie kombinowanie, a sposób na lepszej jakości kod.
Przykład z nazwanymi callbackami dla pełnego obrazu:

function doStuff () {
  database.read("value", doSomethingWithResult)
}

function doSomethingWithResult (result) {
  process(result.text, displayStatus)
}

function displayStatus (success) {
  if (success) {
    console.log('OK')
  }
}

doStuff()

CodePen: https://codepen.io/caderek/pen/pdeEqa?editors=0012

1 użytkowników online, w tym zalogowanych: 0, gości: 1