promise.then ()과 동일한 RxJS 시퀀스?
나는 약속을 가지고 많은 것을 개발하곤했고 지금은 RxJS로 이동하고 있습니다. RxJS의 문서는 프라 미스 체인에서 옵저버 시퀀스로 이동하는 방법에 대한 명확한 예를 제공하지 않습니다.
예를 들어, 저는 보통 다음과 같이 여러 단계로 프로 미스 체인을 작성합니다.
// a function that returns a promise
getPromise()
.then(function(result) {
// do something
})
.then(function(result) {
// do something
})
.then(function(result) {
// do something
})
.catch(function(err) {
// handle error
});
이 약속 체인을 RxJS 스타일로 어떻게 다시 작성해야합니까?
데이터 흐름의 경우 (에 해당 then
) :
Rx.Observable.fromPromise(...)
.flatMap(function(result) {
// do something
})
.flatMap(function(result) {
// do something
})
.subscribe(function onNext(result) {
// end of chain
}, function onError(error) {
// process the error
});
약속은를 사용하여 관찰 가능으로 변환 할 수 있습니다 Rx.Observable.fromPromise
.
일부 약속 연산자는 직접 번역합니다. 예를 들어 RSVP.all
, 또는 jQuery.when
로 대체 될 수 있습니다 Rx.Observable.forkJoin
.
데이터를 비동기 적으로 변환하고 약속으로 수행 할 수 없거나 수행하기 매우 어려운 작업을 수행 할 수있는 많은 연산자가 있다는 점을 기억하십시오. Rxjs는 데이터의 비동기 시퀀스 (즉, 하나 이상의 비동기 값)로 모든 능력을 보여줍니다.
오류 관리의 경우 주제는 조금 더 복잡합니다.
- 거기 캐치 와 마지막으로 통신 사업자도
retryWhen
오류가 발생한 경우 시퀀스를 반복하는 데 도움이 될 수도 있습니다.onError
함수 를 사용하여 구독자 자체의 오류를 처리 할 수도 있습니다.
정확한 의미 체계를 위해 웹에서 찾을 수있는 문서와 예제를 자세히 살펴 보거나 여기에서 특정 질문을 할 수 있습니다.
이것은 Rxjs를 사용하여 오류 관리를 더 깊게하기위한 좋은 출발점이 될 것입니다 : https://xgrommx.github.io/rx-book/content/getting_started_with_rxjs/creating_and_querying_observable_sequences/error_handling.html
보다 현대적인 대안 :
import {from as fromPromise} from 'rxjs';
import {catchError, flatMap} from 'rxjs/operators';
fromPromise(...).pipe(
flatMap(result => {
// do something
}),
flatMap(result => {
// do something
}),
flatMap(result => {
// do something
}),
catchError(error => {
// handle error
})
)
또한이 모든 것이 작동하려면 subscribe
어딘가에이 파이프 가 필요 Observable
하지만 응용 프로그램의 다른 부분에서 처리된다고 가정합니다.
RxJs 6을 사용하여 2019 년 5 월 업데이트
위에 제공된 답변에 동의하고, 명확성을 추가하기 위해 RxJs v6 을 사용하여 장난감 데이터 및 간단한 약속 (setTimeout 포함)이 포함 된 구체적인 예제를 추가하고 싶습니다 .
Just update the passed id (currently hard-coded as 1
) to something that does not exist to execute the error handling logic too. Importantly, also note the use of of
with catchError
message.
import { from as fromPromise, of } from "rxjs";
import { catchError, flatMap, tap } from "rxjs/operators";
const posts = [
{ title: "I love JavaScript", author: "Wes Bos", id: 1 },
{ title: "CSS!", author: "Chris Coyier", id: 2 },
{ title: "Dev tools tricks", author: "Addy Osmani", id: 3 }
];
const authors = [
{ name: "Wes Bos", twitter: "@wesbos", bio: "Canadian Developer" },
{
name: "Chris Coyier",
twitter: "@chriscoyier",
bio: "CSS Tricks and CodePen"
},
{ name: "Addy Osmani", twitter: "@addyosmani", bio: "Googler" }
];
function getPostById(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const post = posts.find(post => post.id === id);
if (post) {
console.log("ok, post found!");
resolve(post);
} else {
reject(Error("Post not found!"));
}
}, 200);
});
}
function hydrateAuthor(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const authorDetails = authors.find(person => person.name === post.author);
if (authorDetails) {
post.author = authorDetails;
console.log("ok, post hydrated with author info");
resolve(post);
} else {
reject(Error("Author not Found!"));
}
}, 200);
});
}
function dehydratePostTitle(post) {
return new Promise((resolve, reject) => {
setTimeout(() => {
delete post.title;
console.log("ok, applied transformation to remove title");
resolve(post);
}, 200);
});
}
// ok, here is how it looks regarding this question..
let source$ = fromPromise(getPostById(1)).pipe(
flatMap(post => {
return hydrateAuthor(post);
}),
flatMap(post => {
return dehydratePostTitle(post);
}),
catchError(error => of(`Caught error: ${error}`))
);
source$.subscribe(console.log);
Output Data:
ok, post found!
ok, post hydrated with author info
ok, applied transformation to remove title
{ author:
{ name: 'Wes Bos',
twitter: '@wesbos',
bio: 'Canadian Developer' },
id: 1 }
The key part, is equivalent to the following using plain promise control flow:
getPostById(1)
.then(post => {
return hydrateAuthor(post);
})
.then(post => {
return dehydratePostTitle(post);
})
.then(author => {
console.log(author);
})
.catch(err => {
console.error(err);
});
if getPromise
function is in a middle of a stream pipe you should simple wrap it into one of functions mergeMap
, switchMap
or concatMap
(usually mergeMap
):
stream$.pipe(
mergeMap(data => getPromise(data)),
filter(...),
map(...)
).subscribe(...);
if you want to start your stream with getPromise()
then wrap it into from
function:
import {from} from 'rxjs';
from(getPromise()).pipe(
filter(...)
map(...)
).subscribe(...);
As far as i just found out, if you return a result in a flatMap, it converts it to an Array, even if you returned a string.
But if you return an Observable, that observable can return a string;
If I understood correctly, you mean consuming the values, in which case you use sbuscribe i.e.
const arrObservable = from([1,2,3,4,5,6,7,8]);
arrObservable.subscribe(number => console.log(num) );
Additionally, you can just turn the observable to a promise using toPromise() as shown:
arrObservable.toPromise().then()
This is how I did it.
Previously
public fetchContacts(onCompleteFn: (response: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => void) {
const request = gapi.client.people.people.connections.list({
resourceName: 'people/me',
pageSize: 100,
personFields: 'phoneNumbers,organizations,emailAddresses,names'
}).then(response => {
onCompleteFn(response as gapi.client.Response<gapi.client.people.ListConnectionsResponse>);
});
}
// caller:
this.gapi.fetchContacts((rsp: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
// handle rsp;
});
After(ly?)
public fetchContacts(): Observable<gapi.client.Response<gapi.client.people.ListConnectionsResponse>> {
return from(
new Promise((resolve, reject) => {
gapi.client.people.people.connections.list({
resourceName: 'people/me',
pageSize: 100,
personFields: 'phoneNumbers,organizations,emailAddresses,names'
}).then(result => {
resolve(result);
});
})
).pipe(map((result: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
return result; //map is not really required if you not changing anything in the response. you can just return the from() and caller would subscribe to it.
}));
}
// caller
this.gapi.fetchContacts().subscribe(((rsp: gapi.client.Response<gapi.client.people.ListConnectionsResponse>) => {
// handle rsp
}), (error) => {
// handle error
});
참고URL : https://stackoverflow.com/questions/34523338/rxjs-sequence-equivalent-to-promise-then
'Program Tip' 카테고리의 다른 글
isset ()에 대한 PHP 속기? (0) | 2020.11.09 |
---|---|
Xcode 6 및 임베디드 프레임 워크는 iOS8에서만 지원됩니다. (0) | 2020.11.08 |
세션이 생성되지 않음 :이 버전의 ChromeDriver는 Selenium을 사용하는 ChromeDriver Chrome에서 Chrome 버전 74 오류 만 지원합니다. (0) | 2020.11.08 |
array.push가 때때로 array [n] = value보다 빠른 이유는 무엇입니까? (0) | 2020.11.08 |
과학적 표기법없이 Double에서 문자열로 변환 (0) | 2020.11.08 |