portaldacalheta.pt
  • Основен
  • Agile Talent
  • Дизайнерски Живот
  • Възходът На Дистанционното
  • Рентабилност И Ефективност
Технология

Включете Angular 2: Надстройка от 1.5



Започнах да искам да напиша ръководство стъпка по стъпка за надграждане на приложение от Angular 1.5 до Angular 2, преди да бъда учтиво информиран от моя редактор, че се нуждае от статия, а не от роман. След дълги размишления, аз приех, че трябва да започна с обширно проучване на промените в Angular 2, удряйки всички точки, обхванати в Jason Aden’s Преминаване на миналия Hello World в Angular 2 статия . ... Ами сега. Продължете и го прочетете, за да получите общ преглед на новите функции на Angular 2, но за практически подход, оставете браузъра си точно тук.

Искам това да се превърне в поредица, която в крайна сметка обхваща целия процес на надстройка на нашето демонстрационно приложение до Angular 2. Засега обаче нека започнем с една услуга. Нека направим една лъкатушеща разходка из кода и ще отговоря на всички въпроси, които имате, като ...



работещи номера на кредитни карти 2017 с пари
‘О, НЕ ЗАЩО ВСИЧКО Е ТОЛКОВА РАЗЛИЧНО’

Ъглова: Старият начин

Ако си като мен, ръководството за бърз старт Angular 2 може би е бил първият път, когато някога сте разглеждали TypeScript. Реално бързо, според собствен уебсайт , TypeScript е „типизиран набор от JavaScript, който се компилира в обикновен JavaScript“. Инсталирате транспилера (подобно на Babel или Traceur) и завършвате с магически език, който поддържа функции на езика ES2015 и ES2016, както и силно писане.



Може да ви успокои да знаете, че нито една от тези тайни настройки не е строго необходима. Не е ужасно трудно напишете Angular 2 код в обикновен стар JavaScript , въпреки че не мисля, че си заслужава да го направя. Хубаво е да разпознаете позната територия, но толкова много от новото и вълнуващото за Angular 2 е по-скоро новият му начин на мислене, отколкото новата му архитектура.



Тази публикация разглежда надстройката на услугата до Angular 2 от 1.5.

Новото и вълнуващото в Angular 2 е по-скоро новият му начин на мислене, отколкото новата му архитектура. Tweet

Така че нека разгледаме тази услуга, която надстроих от Angular 1.5 до 2.0.0-beta.17. Това е доста стандартна услуга Angular 1.x, само с няколко интересни функции, които се опитах да отбележа в коментарите. Това е малко по-сложно от вашето стандартно приложение за играчки, но всичко, което всъщност прави, е да запитва Zilyo, a свободно достъпен API който обобщава списъци от доставчици под наем като Airbnb. Съжаляваме, това е доста малко код.



zilyo.service.js (1.5.5)

'use strict'; function zilyoService($http, $filter, $q) { // it's a singleton, so set up some instance and static variables in the same place var baseUrl = 'https://zilyo.p.mashape.com/search'; var countUrl = 'https://zilyo.p.mashape.com/count'; var state = { callbacks: {}, params: {} }; // interesting function - send the parameters to the server and ask // how many pages of results there will be, then process them in handleCount function get(params, callbacks) { // set up the state object if (params) { state.params = params; } if (callbacks) { state.callbacks = callbacks; } // get a count of the number of pages of search results return $http.get(countUrl + '?' + parameterize(state.params)) .then(extractData, handleError) .then(handleCount); } // make the factory return { get : get }; // boring function - takes an object of URL query params and stringifies them function parameterize(params) { return Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); } // interesting function - takes the results of the 'count' AJAX call and // spins off a call for each results page - notice the unpleasant imperativeness function handleCount(response) { var pages = response.data.result.totalPages; if (typeof state.callbacks.onCountResults === 'function') { state.callbacks.onCountResults(response.data); } // request each page var requests = _.times(pages, function (i) { var params = Object.assign({}, { page : i + 1 }, state.params); return fetch(baseUrl, params); }); // and wrap all requests in a promise return $q.all(requests).then(function (response) { if (typeof state.callbacks.onCompleted === 'function') { state.callbacks.onCompleted(response); } return response; }); } // interesting function - fetch an individual page of results // notice how a special callback is required because the $q.all wrapper // will only return once ALL pages have been fetched function fetch(url, params) { return $http.get(url + '?' + parameterize(params)).then(function(response) { if (typeof state.callbacks.onFetchPage == 'function') { // emit each page as it arrives state.callbacks.onFetchPage(response.data); } return response.data; // took me 15 minutes to realize I needed this }, (response) => console.log(response)); } // boring function - takes the result object and makes sure it's defined function extractData(res) { return res || { }; } // boring function - log errors, provide teaser for greater ambitions function handleError (error) 'Server error'; console.error(errMsg); // log to console instead return errMsg; } // register the service angular.module('angularZilyoApp').factory('zilyoService', zilyoService);

Бръчката в това конкретно приложение е, че показва резултати на карта. Други услуги обработват множество страници с резултати, като прилагат странични или мързеливи скролери, което им позволява да извличат по една чиста страница с резултати наведнъж. Искаме обаче да покажем всички резултати в областта за търсене и искаме те да се появят веднага щом се върнат от сървъра, вместо да се появят внезапно, след като всички страници бъдат заредени. Освен това искаме да показваме актуализации на напредъка на потребителя, така че той да има някаква представа за случващото се.

Свързани: Виталното ръководство за интервюиране с AngularJS

За да постигнем това в Angular 1.5, прибягваме до обратно извикване. Обещания отведете ни до там, както можете да видите от $q.all обвивка, която задейства onCompleted обратно обаждане, но нещата все още стават доста объркани.



След това внасяме лодаш за да създадем всички заявки за страници за нас и всяка заявка е отговорна за изпълнението на onFetchPage обаждане, за да се уверите, че е добавено към картата веднага щом е налице. Но това се усложнява. Както можете да видите от коментарите, аз се изгубих в собствената си логика и не успях да се справя с това, кое кога се връща на какво обещание.

Цялостната изчистеност на кода страда дори повече (много повече, отколкото е строго необходимо), защото след като се объркам, той само спирала надолу от там. Кажи ми, моля те ...



‘ТРЯБВА ДА ИМА ПО-ДОБЪР НАЧИН’

Ъглов 2: нов начин на мислене

Има по-добър начин и ще ви го покажа. Няма да прекарвам твърде много време на концепциите за ES6 (известен още като ES2015), защото има много по-добри места за научаване на тези неща и ако имате нужда от точка за прескачане, ES6-Features.org има добър преглед на всички забавни нови функции. Помислете за този актуализиран код на AngularJS 2:

zilyo.service.ts (2.0.0-beta.17)

import {Injectable} from 'angular2/core'; import {Http, Response, Headers, RequestOptions} from 'angular2/http'; import {Observable} from 'rxjs/Observable'; import 'rxjs/Rx'; @Injectable() export class ZilyoService { constructor(private http: Http) {} private _searchUrl = 'https://zilyo.p.mashape.com/search'; private _countUrl = 'https://zilyo.p.mashape.com/count'; private parameterize(params: {}) { return Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); } get(params: {}, onCountResults) { return this.http.get(this._countUrl, { search: this.parameterize(params) }) .map(this.extractData) .map(results => { if (typeof onCountResults === 'function') { onCountResults(results.totalResults); } return results; }) .flatMap(results => Observable.range(1, results.totalPages)) .flatMap(i => { return this.http.get(this._searchUrl, { search: this.parameterize(Object.assign({}, params, { page: i })) }); }) .map(this.extractData) .catch(this.handleError); } private extractData(res: Response) { if (res.status = 300) { throw new Error('Bad response status: ' + res.status); } let body = res.json(); return body.result || { }; } private handleError (error: any) // In a real world app, we might send the error to remote logging infrastructure let errMsg = error.message }

Готино! Нека да преминем през този ред по ред. Отново, TypeScript преводачът ни позволява да използваме всички функции на ES6, които искаме, защото преобразува всичко във ванилов JavaScript.



import изявленията в началото просто използват ES6 за зареждане на необходимите ни модули. Тъй като правя по-голямата част от разработките си в ES5 (известен още като обикновен JavaScript), трябва да призная, че е малко досадно изведнъж да започна да изброявам всеки обект, който планирам да използвам.

как да изберем шрифт

Имайте предвид обаче, че TypeScript пренася всичко в JavaScript и тайно използва SystemJS за справяне с натоварването на модула. Всички зависимости се зареждат асинхронно и той (уж) може да групира вашия код по начин, който премахва символи, които не сте импортирали. Плюс това всичко поддържа „агресивна минификация“, което звучи много болезнено. Тези декларации за внос са малка цена, която трябва да се плати, за да се избегне справянето с целия този шум.



Импортирането на изявления в Angular прави много зад кулисите.

Извлеченията за внос са малка цена за това, което се случва зад кулисите.

Както и да е, освен зареждането в селективни функции от самия Angular 2, обърнете специално внимание на линията import {Observable} from 'rxjs/Observable';. RxJS е умопомрачителна, безумно готина библиотека за реактивно програмиране, която предоставя част от инфраструктурата, лежаща в основата на Angular 2. Определено ще чуем от нея по-късно.

Сега стигаме до @Injectable().

Все още не съм напълно сигурен какво прави това, за да бъда честен, но красотата на декларативното програмиране е, че не винаги трябва да разбираме подробностите. Нарича се декоратор, което е изискана конструкция на TypeScript, способна да приложи свойства към класа (или друг обект), който го следва. В този случай, @Injectable() учи нашата служба как да се инжектира в даден компонент. Най-добрата демонстрация идва направо от устата на коня, но е доста дълга, така че ето един кратък поглед как изглежда в нашия AppComponent:

@Component({ ... providers: [HTTP_PROVIDERS, ..., ZilyoService] })

Следва самото определение на класа. Той има export изявление преди него, което означава, познахте, можем import нашата услуга в друг файл. На практика ще импортираме нашата услуга в нашата AppComponent компонент, както по-горе.

@Injectable () учи нашата услуга как да се инжектира в компонент.

@Injectable () учи нашата услуга как да се инжектира в компонент.

Веднага след това е конструкторът, където можете да видите действително инжектиране на зависимост в действие. Линията constructor(private http:Http) {} добавя променлива на частен екземпляр, наречена http че TypeScript магически разпознава като екземпляр на услугата Http. Точката отива към TypeScript!

графичният дизайн не е изкуство

След това са само някои редовно изглеждащи променливи на екземпляра и полезна функция, преди да стигнем до истинското месо и картофи, get функция. Тук виждаме Http в действие. Прилича много на основания на обещания подход на Angular 1, но под капака е доста по-хладно. Изграждането на RxJS означава, че получаваме няколко големи предимства пред обещанията:

  • Можем да анулираме Observable ако вече не ни интересува отговорът. Това може да е така, ако изграждаме поле за автоматично попълване на typeahead и вече не се интересуваме от резултатите за „ca“, след като въведат „cat“.
  • Observable може да излъчва множество стойности и абонатът ще бъде извикан отново и отново, за да ги консумира, докато се произвеждат.

Първият е страхотен при много обстоятелства, но вторият, върху който се фокусираме в новата ни услуга. Нека да преминем през get функция ред по ред:

конвертирайте заплатата в договорна ставка
return this.http.get(this._countUrl, { search: this.parameterize(params) })

Изглежда доста подобно на HTTP повикване, основано на обещание, което бихте видели в Angular 1. В този случай изпращаме параметрите на заявката, за да получим броя на всички съвпадащи резултати.

.map(this.extractData)

След като повикването AJAX се върне, то ще изпрати отговора надолу по потока. Методът map е концептуално подобен на масив map функция, но също така се държи като обещание then метод, тъй като чака всичко, което се случва нагоре по веригата, да завърши, независимо от синхронността или асинхронността. В този случай той просто приема обекта за отговор и дразни данните JSON, за да ги предаде надолу по веригата. Сега имаме:

.map(results => { if (typeof onCountResults === 'function') { onCountResults(results.totalResults); } return results; })

Все още имаме едно неудобно обратно извикване, което трябва да вмъкнем там. Вижте, не всичко е магия, но можем да обработим onCountResults веднага щом повикването AJAX се върне, и то без да напуска нашия поток. Това не е лошо. Що се отнася до следващия ред:

.flatMap (резултати => Observable.range (1, results.totalPages))

О, о, можеш ли да го почувстваш? Една фина тишина се появи над гледащата тълпа и можете да разберете, че нещо голямо ще се случи. Какво означава тази линия? Дясната част не е толкова луда. Създава диапазон RxJS, който мисля като прославен Observable -обвит масив. Ако results.totalPages е равно на 5, в крайна сметка получавате нещо като Observable.of([1,2,3,4,5]).

flatMap е, изчакайте, комбинация от flatten и map. Има страхотно видео, обясняващо концепцията на Egghead.io , но моята стратегия е да мисля за всеки Observable като масив. Observable.range създава своя собствена обвивка, оставяйки ни с двумерния масив [[1,2,3,4,5]] flatMap изравнява външния масив, оставяйки ни с [1,2,3,4,5], след това map просто съпоставя масива, като предава стойностите надолу по верига една по една. Така че този ред приема цяло число (totalPages) и го преобразува в поток от цели числа от 1 до totalPages. Може да не изглежда много, но това е всичко, което трябва да настроим.

ПРЕСТИЖА

Наистина исках да разкажа това на една линия, за да увеличи въздействието му, но предполагам, че не можете да ги спечелите всички. Тук виждаме какво се случва с потока от цели числа, който зададохме на последния ред. Те се вливат в тази стъпка един по един, след което се добавят към заявката като параметър на страницата, преди накрая да бъдат пакетирани в чисто нова заявка AJAX и изпратени, за да извлекат страница с резултати. Ето този код:

.flatMap(i => { return this.http.get(this._searchUrl, { search: this.parameterize(Object.assign({}, params, { page: i })) }); })

Ако totalPages беше 5, конструираме 5 GET заявки и ги изпращаме едновременно. flatMap се абонира за всеки нов Observable, така че когато заявките се върнат (в произволен ред), те се разгъват и всеки отговор (като страница с резултати) се изтласква един по един надолу по веригата.

Нека да разгледаме как цялото това нещо работи от друг ъгъл. От нашата първоначална заявка за „преброяване“ намираме общия брой страници с резултати. Създаваме нова AJAX заявка за всяка страница и без значение кога се връщат (или в какъв ред), те се изтласкват в потока веднага щом са готови. Всичко, което трябва да направи нашият компонент, е да се абонира за Observable, върнато от нашите get метод и той ще получи всяка страница, една след друга, всички от един поток. Вземете това, обещания.

Всеки отговор се изтласква един по един надолу по веригата.

Компонентът ще получава всяка страница, една след друга, всички от един поток.

Всичко това е малко антиклиматично след това:

Power pivot таблица excel 2013
.map(this.extractData).catch(this.handleError);

Тъй като всеки обект на отговор пристига от flatMap, неговият JSON се извлича по същия начин като отговора от заявката за преброяване. Прикрепен към края има catch оператор, който помага да се илюстрира как се базира потока RxJS обработка на грешки върши работа. Това е доста подобно на традиционната парадигма try / catch, с изключение на това, че Observable object работи и за асинхронна обработка на грешки.

Всеки път, когато се срещне грешка, тя се състезава надолу по веригата, прескачайки минали оператори, докато не срещне манипулатор на грешки. В нашия случай handleError метод повторно изхвърля грешката, позволявайки ни да я прихванем в рамките на услугата, но също така да позволим на абоната да предостави своя собствена onError обратен разговор, който се задейства още по-надолу по течението. Обработката на грешки ни показва, че не сме се възползвали напълно от потока си, дори с всички страхотни неща, които вече сме постигнали. Тривиално е да добавите retry оператор след нашите HTTP заявки, който изпробва индивидуална заявка, ако върне грешка. Като превантивна мярка бихме могли да добавим и оператор между range генератор и заявките, добавяйки някаква форма на ограничаване на скоростта, така че да не спамим сървъра с твърде много заявки наведнъж.

Свързани: Наемете най-добрите 3% от разработчиците на свободна практика AngularJS.

Обобщение: Learning Angular 2 не е само нова рамка

Изучаването на Angular 2 е по-скоро като среща с изцяло ново семейство и някои от отношенията им са сложни. Надяваме се, че успях да докажа, че тези взаимоотношения са се развили по някаква причина и има много да се спечели, като се зачита динамиката, която съществува в тази екосистема. Надяваме се, че и тази статия ви е харесала, защото едвам съм надраскал повърхността и има много още какво да кажа по този въпрос.

Свързани: Всички предимства, без караница: Урок за ъглови 9

Репликация на MySQL Master-Slave на същата машина

Back-End

Репликация на MySQL Master-Slave на същата машина
Front-End Frameworks: Решения или огромни проблеми?

Front-End Frameworks: Решения или огромни проблеми?

Технология

Популярни Публикации
Широки срещу тесни набори от умения: Демистифицирани умения за софтуерно инженерство
Широки срещу тесни набори от умения: Демистифицирани умения за софтуерно инженерство
Талантът не е стока
Талантът не е стока
iOS 9 Betas и WatchOS 2 за разработчици
iOS 9 Betas и WatchOS 2 за разработчици
Ръководство за многообработващи мрежови сървърни модели
Ръководство за многообработващи мрежови сървърни модели
Как да създадете персонализирани шрифтове: 7 стъпки и 3 казуса
Как да създадете персонализирани шрифтове: 7 стъпки и 3 казуса
 
Настройка на производителността на базата данни на SQL за разработчици
Настройка на производителността на базата данни на SQL за разработчици
Събуждане на спяща индустрия: Нарушаване на индустрията на матраците
Събуждане на спяща индустрия: Нарушаване на индустрията на матраците
Figma срещу Sketch срещу Axure - Преглед, основан на задачи
Figma срещу Sketch срещу Axure - Преглед, основан на задачи
Разбиране на нюансите на класификацията на шрифтовете
Разбиране на нюансите на класификацията на шрифтовете
Възраст преди красотата - Ръководство за дизайн на интерфейси за възрастни възрастни
Възраст преди красотата - Ръководство за дизайн на интерфейси за възрастни възрастни
Популярни Публикации
  • крива на търсенето се изгражда при предположението, че
  • хакнати кредитни карти със защитен код
  • какъв език за програмиране използва windows
  • дефиниция на дизайна в чл
  • Структурна диаграма на фонда за дялово участие
  • sql сървърът използва разширена версия на sql, наречена t-sql или transact-sql.
Категории
  • Agile Talent
  • Дизайнерски Живот
  • Възходът На Дистанционното
  • Рентабилност И Ефективност
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt