Angular 7: отправить ответное сообщение от сервиса

Функции стрелок были созданы для упрощения функции scope и решения ключевого слова this, упростив ее. Они используют синтаксис =>, который выглядит как стрелка.

Примечание: он не заменяет существующие функции. Если вы замените каждый синтаксис функций на функции со стрелками, он не будет работать во всех случаях.

Давайте посмотрим на существующий синтаксис ES5. Если ключевое слово this находилось внутри метода объекта (функция который принадлежит объекту), к чему это относится?

var Actor = {
  name: 'RajiniKanth',
  getName: function() {
     console.log(this.name);
  }
};
Actor.getName();

Вышеприведенный фрагмент ссылается на object и печатает имя "RajiniKanth". Давайте рассмотрим нижеприведенный фрагмент и посмотрим, что здесь будет здесь.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach(function(movie) {
     alert(this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

. А теперь, если ключевое слово this находилось внутри method’s function?

Здесь это будет означать window object, чем inner function, как его выпавшее из scope. Поскольку this всегда ссылается на владельца функции, в которой он находится, для этого случая - поскольку он теперь выходит из области видимости - объект window / global.

Когда он находится внутри object 's метод - владелец function является объектом. Таким образом, это ключевое слово привязано к объекту. Однако, когда он находится внутри функции, как автономной, так и внутри другого метода, она всегда будет ссылаться на объект window/global.

var fn = function(){
  alert(this);
}

fn(); // [object Window]

Есть способы решить эту проблему в нашем ES5 сам, рассмотрим, что перед тем, как погрузиться в функции ES6 arrow, как решить проблему.

Как правило, вы должны создать переменную вне внутренней функции метода. Теперь метод ‘forEach’ получает доступ к this и, следовательно, к свойствам object’s и их значениям.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   var _this = this;
   this.movies.forEach(function(movie) {
     alert(_this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

, используя bind, чтобы прикрепить ключевое слово this, которое ссылается на метод method’s inner function.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach(function(movie) {
     alert(_this.name + " has acted in " + movie);
   }).bind(this);
  }
};

Actor.showMovies();

Теперь с помощью функции стрелки ES6 мы можем более эффективно решить проблему lexical scoping.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach((movie) => {
     alert(this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

Arrow functions больше похожи на операторы функций, за исключением того, что они bind это parent scope. Если аргумент arrow function is in top scope, this будет ссылаться на window/global scope, тогда как функция стрелки внутри регулярной функции будет иметь свой этот аргумент так же, как и внешнюю функцию.

С функциями arrow this привязан к закрытию scope во время создания и не может быть изменен. Новый оператор, bind, call и apply не влияют на это.

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
  callback(param);
  }, 1);
};

// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
  doSomething: function () {
  // Here we pass `o` into the async function,
  // expecting it back as `param`
  asyncFunction(o, function (param) {
  // We made a mistake of thinking `this` is
  // the instance of `o`.
  console.log('param === this?', param === this);
  });
  }
};

o.doSomething(); // param === this? false

В приведенном выше примере мы потеряли контроль над этим. Мы можем решить приведенный выше пример, используя переменную ссылку this или используя bind. С ES6 становится легче управлять this в качестве привязки к lexical scoping.

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
  callback(param);
  }, 1);
};

var o = {
  doSomething: function () {
  // Here we pass `o` into the async function,
  // expecting it back as `param`.
  //
  // Because this arrow function is created within
  // the scope of `doSomething` it is bound to this
  // lexical scope.
  asyncFunction(o, (param) => {
  console.log('param === this?', param === this);
  });
  }
};

o.doSomething(); // param === this? true

Если не функции стрелки

Внутри литерала объекта.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  getName: () => {
     alert(this.name);
  }
};

Actor.getName();

Actor.getName определяется функцией стрелки, но при вызове он оповещает о неопределенности, поскольку this.name является undefined, поскольку контекст остается в window.

Это происходит потому, что функция стрелки связывает контекст лексически с внешним окружением window object ... i.e. Выполнение this.name эквивалентно window.name, которое не определено.

Прототип объекта

Это же правило применяется при определении методов на prototype object. Вместо использования функции-стрелки для определения метода sayCatName, который приводит к некорректному context window:

function Actor(name) {
  this.name = name;
}
Actor.prototype.getName = () => {
  console.log(this === window); // => true
  return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined

Конструкторы Invoke

this в вызове построения - это вновь созданный объект , При выполнении нового Fn () контекст constructor Fn является новым объектом: this instanceof Fn === true.

this настроен из охватывающего контекста, то есть внешней области, которая делает ее не назначенной вновь созданному объекту.

var Message = (text) => {
  this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');

Обратный вызов с динамическим контекстом

Функция Arrow связывает декларацию context статически и не может сделать ее динамической. Присоединение прослушивателей событий к элементам DOM является общей задачей при программировании на стороне клиента. Событие запускает функцию обработчика с этим в качестве целевого элемента.

var button = document.getElementById('myButton');
button.addEventListener('click', () => {
  console.log(this === window); // => true
  this.innerHTML = 'Clicked button';
});

this - это окно в функции стрелки, которая определена в глобальном контексте. Когда происходит событие клика, браузер пытается вызвать функцию обработчика с контекстом кнопки, но функция стрелки не изменяет свой предварительно определенный контекст. this.innerHTML эквивалентен window.innerHTML и не имеет смысла.

Вы должны применить выражение функции, которое позволяет изменить это в зависимости от целевого элемента:

var button = document.getElementById('myButton');
button.addEventListener('click', function() {
  console.log(this === button); // => true
  this.innerHTML = 'Clicked button';
});

Когда пользователь нажимает кнопку, это в функции обработчика является кнопкой. Таким образом, this.innerHTML = 'Clicked button' корректно изменяет текст кнопки, чтобы отразить статус щелчка.

Ссылки: https://rainsoft.io/when-not-to-use-arrow-functions-in-javascript/

0
задан James D. Carillo 16 January 2019 в 10:04
поделиться

3 ответа

Угловые шаблоны будут искать переменные только в компоненте, который мы объявили в них. Так что внесите изменения, как показано ниже в вашем шаблоне

<p> {{service.message}} </p>

Здесь service - это то, что вы вводите в свой компонент.

Если вы объявите message:string в своем сервисе, это нормально, по умолчанию переменные являются общедоступными, и мы можем получить к ним доступ в шаблонах. Но с помощью служебной переменной мы вводим их через конструктор.

Я надеюсь, что это решит вашу проблему :)

0
ответ дан ganesh045 16 January 2019 в 10:04
поделиться

Вы не можете получить доступ к полям компонента в сервисе. Вам нужно каким-то образом передать ответ службы, и только тогда вы сможете использовать этот ответ и на основе этого присваивать значение сообщению и отображать его в своем html.

Я думаю, что вы должны использовать обратный вызов, в котором вы обернете ответ вашего http-запроса и будете использовать его на внешнем уровне обслуживания.

signIn(username: string, password: string, data:any) {
    const formData = ...
    this.http.post(`${this.uri}`, formData, httpOptions)
        .subscribe(response => {
        data(response);
    }, error => data(// do something here);
}

теперь используйте это как-то так (в компоненте, я думаю):

message: String;

this.restService.signIn(userName, password, response => {
    if(response && response.hasOwnProperty('statusCode')) {
        if (response['statusCode'] === '0') {
           this.message = 'test';    
        } else {
           this.message = 'test2';
        }
    }
});

теперь вы можете использовать сообщения в HTML [116 ]

{{message}}

ПРИМЕЧАНИЕ

Всегда следует использовать уровень обслуживания только для передачи данных (если это услуга rest / api), в некоторых случаях следует использовать бизнес-логику или манипулирование данными. промежуточный уровень обслуживания или компонент.

Таким образом, вы можете сделать общий сервис отдыха и использовать его во всех приложениях, вам просто нужно передать тело запроса, URL и объект обратного вызова.

Если вы собираетесь писать логику в сервисе, вам придется писать отдельный сервис для каждого вызова API.

0
ответ дан user3145373 ツ 16 January 2019 в 10:04
поделиться

Я полагаю, ваш пример кода является частью класса обслуживания: вы не можете получить доступ к атрибутам службы, таким как message или message2, из вашего HTML-шаблона. Вы должны вернуть HTTP, наблюдаемый контроллеру, и поместить логику подписки в свой контроллер.

Служба:

return this.http.post(`${this.uri}`, formData, httpOptions);

Контроллер:

сообщение: строка;

вход (имя пользователя, пароль): наблюдаемый {

this.cookieService.deleteAll();

this.ls.signIn(username, password).subscribe(res =>
  const self = this;
  xml2js.parseString(res, function (err, result) {
    const statusCode = ...
    console.log(statusCode); // it getting statusCode
    if (statusCode === '0') {
      self.message = 'test'; 
    } else {

    }
  }));
  return;

}

0
ответ дан Benjamin Caure 16 January 2019 в 10:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: