God said, let there be a code, and so bathed in incense, with a stroke of the pen, a Hello World

console.log('Hello world')
Copy the code

God wasn’t happy about that. He only wanted to show the result when needed, so we put it in a function box called callback:

function callback() {
  console.log('Hello world')}Copy the code

The program in the box doesn’t execute on its own, it only executes when we call it, satisfying God’s needs, and one thing we learned:

Functions can be used as a means to delay code execution

The actor is in place

Imagine a situation where we need a reminder that it’s time to drink water, so we can do something like this:

function reminder() {
  console.log('Time to drink water! ') / / 1
}
reminder() // Time to drink water!
Copy the code

This looks like a good idea, but we’d prefer it to just do the reminding, and what to do after the reminding (line 1) is up to us. To do this, we can pass in the concrete logic as a function argument:

function reminder(cb) {
  cb()
}
reminder((a)= > console.log('Time to drink water! ')) // Time to drink water!
Copy the code

The code has the same effect, but here we are free to change the behavior of the notification event by passing in different function parameters.

Here’s a reminder:

function reminder(cb) {
  cb()
  setTimeout((a)= > {
    cb()
  }, 1000)
}
reminder((a)= > console.log('Time to drink water! '))
Copy the code

The code above will alert you immediately and then again a second later.

The reality is not always satisfactory, our Reminder can be wrong and we would like to know when this series of reminders will end, but for now reminder only has one CB parameter which is not enough for us. The simplest way is to pass in three parameters for use:

  • One is named next when the alert event occurs
  • One is called error when an error occurs
  • One is when the reminder ends, name it Complete

If we use an object to wrap these three parameters:

function reminder(cb) {
  cb.next(1)
  cb.complete()
}
reminder({
  next: v= > console.log('Time to drink water! ', v),
  error: e= > console.log(e),
  complete: (a)= > console.log('Done'})),// Time to drink water! 1
// Done
Copy the code

Let’s put reminder in a reminder class and rename the Remind method:

class Reminder {
  remind(cb) {
    cb.next(1)
    cb.complete()
  }
}

const reminder = new Reminder()

reminder.remind({
  next: v= > console.log('Time to drink water! ', v),
  error: e= > console.log(e),
  complete: (a)= > console.log('Done'})),Copy the code

Reminder that the logic can be dynamically injected. One solution is to pass in the contents of the function body as a constructor parameter:

class Reminder {
  constructor(behavior) {
    this.behavior = behavior
  }
  remind(cb) {
    this.behavior(cb)
  }
}

const reminder = new Reminder(cb= > {
  cb.next(1)
  cb.complete()
})

reminder.remind({
  next: v= > console.log('Time to drink water! ', v),
  error: e= > console.log(e),
  complete: (a)= > console.log('Done'})),Copy the code

So let’s do some renaming

  • ReminderObservable
  • remindsubscribe
  • cbobserver
  • reminderobs$
class Observable {
  constructor(behavior) {
    this.behavior = behavior
  }
  subscribe(observer) {
    this.behavior(observer)
  }
}

const obs$ = new Observable(observer= > {
  observer.next(1)
  observer.complete()
})
const observer = {
  next: v= > console.log('Time to drink water! ', v),
  error: e= > console.log(e),
  complete: (a)= > console.log('Done'),
}
obs$.subscribe(observer)
Copy the code

At this point, in 20 lines of code, including even a blank line at the end of the file, we’ve implemented an Observable

thinking

Through a series of requirements changes and embrace changes, we refactored the original Hello World into a basic Observable. Observe and consider the above code again. In addition to the Observable definition, there are three statements:

  • obs$And, most importantly, it defines the behavior of the observed
  • observerDefines behavior when observed events occur
  • subscribeThe call to connectObservableobserverWithout this connection, nothing happens. Right

These three statements have a single, distinct responsibility and provide a great way to organize your code.

Question 1:ObservableIs it asynchronous?

Looking at its internal implementation, it all depends on whether its implementation calls next, Error, and complete asynchronously.

Question 2: Relationship between RxJS and Observable

Based on Observables, RXJS provides a large number of operators to help implement complex Observable behavior definitions.

Welcome to lambdaIO on wechat