角度2+,使用Promise并没有给出我想要的结果

时间:2018-04-12 08:39:56

标签: angular promise mean

我正在调用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)
    }
  })
}

4 个答案:

答案 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
}

通过这样做你也可以摆脱你创建的所有计数器和数组索引跟踪。