我正在调用createPublicPostContent()方法,该方法正在运行一个创建数组的for循环" tempArray" 然而,在第一个循环(i = 0)之后,Promise已经解决了。如何在所有循环完成后确保promise只能解决? 我尝试将解决方案放在循环中,但这并没有改变结果。
createPublicPostContent = (arrayOfPosts) => {
var tempArray = []
return new Promise((resolve, reject) => {
let error = false;
var i = 0;
for (let key of arrayOfPosts) {
if (key.coinCode == this.currentCoinCode) {
steem.api.getContent(key.autheur, key.permlink,
((err, result) => {
this.authorPostPublic = (result['author'])
tempArray[i] = {
"_id": key._id,
"item1": this.postItem,
"item2": this.postItem2
}
i++
var size = Object.keys(this.publicPostGrade[0]).length;
}))
}
}
if (error) {
reject('error')
} else {
resolve(tempArray)
}
})
}
答案 0 :(得分:1)
你可以这样做,因为你有多个值
getItems(ids: number[]): Observable<Post> {
return <Observable<Post>> forkJoin(
ids.map(id => <Observable<Post>>
this.httpClient.get(`item/${id}`)
.catch((err: HttpErrorResponse) => {
console.error('An error occurred:', err.error);
})
)
).pipe(concatAll());
}
注意:forkJoin等待所有请求完成,输出顺序与传递顺序相同。正确处理错误,好像一个失败都失败了。我建议根据请求使用.catch()
函数来避免
或
getItems(ids: number[]): Observable<Item> {
return from(ids).pipe(
mergeMap(id => <Observable<Item>> this.httpClient.get(`item/${id}`))
);
}
注意:mergemap的问题请求顺序与输出顺序不一样。但是有办法在帖子中处理它。
检查一下:Practical RxJS In The Wild — Requests with concatMap() vs mergeMap() vs forkJoin()这篇文章展示了如何处理多个案例,就像你所拥有的场景一样。
答案 1 :(得分:1)
Long
答案 2 :(得分:1)
您从api中获取异步的数据,原因如下:
createPublicPostContent = (arrayOfPosts) => {
var tempArray = []
return new Promise((resolve, reject) => {
let error = false;
var i = 0;
var expectedApiCount = 0;
var apiResponseCount = 0;
arrayOfPosts.forEach(key => {
if (key.coinCode == this.currentCoinCode) {
expectedApiCount++;
steem.api.getContent(key.autheur, key.permlink,
((err, result) => {
apiResponseCount++;
this.authorPostPublic = (result['author'])
tempArray[i] = {
"_id": key._id,
"item1": this.postItem,
"item2": this.postItem2
}
i++;
var size = Object.keys(this.publicPostGrade[0]).length;
if (error) {
reject('error')
} else if(apiCount == expectedApiCount) {
resolve(tempArray)
}
}))
}
});
})
}
答案 3 :(得分:0)
异步库可以轻松解决您的问题。只需在组件中声明一个异步函数,然后等待解析你的createPublicPostContent函数:
async myAsyncFunction () {
const res = await createPublicPostContent()
// this block is executed only after you get your promise resolved/rejected
// in here you can use the resolved variable
}
我在你的代码中注意到的一件事是你在forEach循环中解析...你不应该这样做,因为这个循环和所有其他循环一样是异步的。这意味着在调用steem.api.getContent函数之后,下一个循环会立即启动,并且不会等待它完成。因此,您的解决/拒绝将通过您从api收到的第一个答案执行,它可能来自第二个,第三个或更多的电话,而不是第一个。
如果你想从你的api获得所有答案,然后在那之后做一些动作,你应该将它们存储在一个数组中,然后等待使用Promise.all(array)解析整个数组。像这样:
getApiData (key) {
return new Promise((resolve, reject) => {
if (key.coinCode == this.currentCoinCode){
var obj
steem.api.getContent(key.autheur, key.permlink, ((err, result) => {
this.authorPostPublic = (result['author'])
obj = {
"_id": key._id,
"item1":this.postItem,
"item2" : this.postItem2
}
var size = Object.keys(this.publicPostGrade[0]).length
if (err) {
reject('error')
}
else {
resolve (obj)
}
}))
}
})
}
async createPublicPostContent (arrayOfPosts) {
var tempArray = []
for (let key of arrayOfPosts) {
tempArray.push(getApiData(key))
}
var response = await Promise.all(tempArray)
return response
}
通过这样做你也可以摆脱你创建的所有计数器和数组索引跟踪。