Promise在循环调用提供程序完成之前解析

时间:2018-01-29 01:24:18

标签: promise rxjs ionic3 observable angular-promise

我遇到了一些Ionic 3应用程序代码的问题。

基本上,我有一个所有具有唯一ID的对象列表。必须通过GET请求发送每个对象的唯一ID,以便我们可以从服务器获取每个对象的相应数据。这必须基于每个对象完成;我无法将它们捆绑到一个请求中,因为没有API端点。

因此,对象都存储在一个数组中,因此我一直在尝试遍历数组并为每个对象调用提供程序。请注意,提供程序正在返回一个observable。

由于提供程序是一个异步函数,因此在循环结束之前,promise将解析,除非我超出promise解析。这违背了承诺的全部要点。

我应该采取什么样的正确方法,以便在promise解决之前完成循环提供程序调用?

如果我在循环完成时有内心的承诺解决,它是否也会过早解决?

我还读到,打开一堆可观察量是不好的。我是否应该使用toPromise()将每个observable作为承诺返回?

以下是构建数据的代码:

asyncBuildData() {
    var promise = new Promise((resolve, reject) => {
        let completedRequests = 0;
        for (let i = 0; i < 10; i++) {
            this.provider.getStuffById(listOfStuff[i].id).subscribe(val => {
                list.push(val)
                completedRequests++;
            })
        }
        console.log('cp', completedRequests); // completedRequests = 0
        setTimeout(() => {
            console.log('cp', completedRequests); // completedRequests = 10
            let done = true;
            if (done) {
                resolve('Done');
            } else {
                reject('Not done');
            }
        }, 1500)
    })
    return promise;
}

提供商代码:

getStuffById(stuffId) {
    let url = url + stuffId;
    return this.http.get(url)
        .map(res => res.json());
}

2 个答案:

答案 0 :(得分:1)

即使您无法将它们捆绑到一个请求中,您仍然可以将它们捆绑到一个可观察对象中,并使用.forkJoin()并行触发这些请求:< / p>

buildData$() {
    let parallelRequests = listOfStuffs.map(stuff => this.provider.getStuffById(stuff.id));

    return Observable.forkJoin([...parallelRequests]);
}

然后在您的组件中,您可以致电:

buildData$.subscribe(val=>{
    //val is an array of all the results of this.provider.getStuffById()
    list =val;
})

请注意,Obersvable.forkJoin()将在发出任何值之前完成所有请求。

答案 1 :(得分:0)

如果我理解正确,那么以下代码可以帮助您顺利进行。这将为数组中的每个元素一次执行一个promise。

        var ids = [1,2,3,4,5];

        ids.reduce(function (promise, id) {
            return promise.then(function () {
                let url = url + id;
                return this.http.get(url)
                           .map(res => res.json());
            });
        }, Promise.resolve()).then(function(last) {
            // handle last result
        }, function(err) {
            // handle errors
        });

我用jQuery帖子对它进行了测试,然后用你的Ionic替换它。如果失败,请告诉我。