Showing posts with label promise. Show all posts
Showing posts with label promise. Show all posts

3/25/19

Implementing javascript Promise by myself

Motivation

I remember that once (at some job interview) i was asked to write the Promise implementation by myself. Since it was long ago, and i dont remember what i wrote then (or if) - I decided to take the challenge again.
So i will write here about the process of implementation step by step.

Class

First of all - i decided to take advantage of ES6 feature - the classes, which makes you to write classes instead of functions:


// using ES6 "class" feature
class MyPromise {
  constructor() {
    console.log('constructor called');
  }
}
const p = new MyPromise();

Executor

One of the most significant specifications of Promise - is that it must receive an "executor" as parameter
Executor must be passed by user and it must be function
I implemented it - by placing executor as a constructor parameter:


class MyPromise {
  constructor(executor) {
    executor();
  }
}
// must get executor fired 
const p = new MyPromise(()=>{
  console.log('executor fired')
});

Resolve and Reject

A Promise executor must have two parameters - resolve and reject.
These "resolve" and "reject" are promise methods which can be passed as parameters to function where user can inject them according to his needs


// passing "res" and "rej" memebers to executor
class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  resolve() {
    console.log('resolve fired');
  }
  reject() {
    console.log('reject fired');
  }  
}
const p = new MyPromise((res, rej)=>{
  res(); // calling the resolve
});

Then

Until now it was pretty easy...
Now comes the hard part: the "then"
The Promise must return the "then" and "catch" methods in which user should be able to pass success and error callbacks
It is not difficult to get "then" method returned:


class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject);
  }
  ...
  ...
  then() { // then added to "myPromise" object
 
  }
  catch(err)  {
    
  }
}

The goal here is to get "success" callback to fire if "resolve" method called inside the executor
Here where is had 2 difficulties:
- the success callback must be already set when resolve method called (since resolve must trigger it! )
- how to pass "this" into resolve, since it called from "outside"!
I manage to solve the first obstacle by using "setTimeout", to call the executor asyncronously

// then must be returned
class MyPromise {
  constructor(executor) {
    setTimeout(()=>{executor(() => this.resolve(), () => this.reject());});   
  }
  
  resolve() {
   this.success && this.success(); // this.success should be set before resolve called 
  }
  reject() {
    console.log('reject fired');
  }
  then(cb) {
    this.success = cb;
  }
  catch(err)  {
    
  }
}
const p = new MyPromise((res, rej) => {
  res();
});
p.then(() => {
   console.log(`then callback fired `);
})

Data of Resolve

The last specification i decided to implement - is make "resolve" to able pass data to "success"
Here is what i come with:


//  "res" should pass data
class MyPromise {
  constructor(executor) {
    setTimeout(()=>{executor((d) => this.resolve(d), () => this.reject());}); 
  }
  
  resolve(data) {
   this.success(data);
  }
  reject() {
    console.log('reject fired');
  }
  then(cb) {
    this.success = cb;
  }
  catch(err)  {
    
  }
}
const p = new MyPromise((res, rej) => {
  res('o'); // "o" is the example data
});
p.then((data) => {
   console.log(`then fired ${data}`);
})

Summary

The "creating my own Promise" challenge - made me to think about few interesting question I nave not thought until now
I'm not sure i did the best solution possible here, but now i have motivation to look and search for implementations of better javascript coders ...

3/27/16

Using Promises In Angular2

In the last post we created our first angular service. This service served only some static data for chart componentt we build in previous posts.
Everybody knows that to serve static data is not cool.
The really though guys use services for bring data from server.
In other words - real service must use is promises.

Promises In Angular2

For one who used promises in angular 1. to use promise in angular2 is pretty simple:


@Injectable()
export class FlotService {
  getFlotEntries() {
    return Promise.resolve(FlotEntries);
  }
}

Yes, the same old good Promise.resolve. And for consume the service we should use the same old "then"

export class App implements OnInit {
  
  private dataset:any;
  public entries;  
  getEntries() {
    this._flotService.getFlotEntries().then(
                       entries => this.dataset[0].data = entries,
                       error =>  this.errorMessage = error);
  } 

Now lets make our chart component to work with this service.

Projecting data into component

The issue i had run into is that while the call to the service is on the main "App" component, the place i want data to be displayed is on the inner component - "Flot", which getting chart "data" property as input parameter:


<flot  [options]="splineOptions" [dataset]="dataset" height="250px" width="100%"></flot>

In angular 1. all data changes are observed and immediately projected after the change is located by digest cycle.
In angular2 - not in all cases. Angular2 change detection doesn't observe the content only the value or reference itself (angular2 observes only "dataset" but not inner property "data")

A workaround

One way to make angular2 to watch the inner properties changes is to use ngDoCheck().
ngDoCheck() is called every change detection cycle, whether or not there are any input property changes.(great thanks to these guys for this information)
Now we need to modify flot component - so it start to use OnChanges:


import {Component, ElementRef, Input} from 'angular2/core';

@Component({
  selector: 'flot',
  template: `
loading
` }) export class FlotCmp{ ... ngOnInit() { if(!FlotCmp.chosenInitialized) { let plotArea = $(this.el.nativeElement).find('div').empty(); plotArea.css({ width: this.width, height: this.height }); $.plot( plotArea, this.dataset, this.options); FlotCmp.chosenInitialized = true; } } ngDoCheck() { if(this.dataset[0].data !== null && !this.dataPlotted) { console.log('plotting data'); let plotArea = $(this.el.nativeElement).find('div').empty(); $.plot( plotArea, this.dataset, this.options); this.dataPlotted = true; } } }
Now the child component view reacts to changes of flot data

Here is running code: Hope you have fun reading...

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...