【问题标题】:Promise resolves before looping calls to provider finishPromise 在循环调用提供者完成之前解决
【发布时间】:2018-07-07 16:08:48
【问题描述】:

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

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

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

由于提供者是一个异步函数,因此 Promise 将在循环完成之前解析,除非我超时了 Promise 解析。这违背了承诺的全部意义。

我应该这样做的正确方法是什么,以便在承诺解决之前完成循环提供程序调用?

如果我有一个在循环完成时解决的内部承诺,它不会也过早解决吗?

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

这是构建数据的代码:

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());
}

【问题讨论】:

标签: promise rxjs ionic3 observable angular-promise


【解决方案1】:

即使您不能将它们捆绑到一个请求中,您仍然可以将它们捆绑到 一个 observable,其中这些请求是并行触发的,使用.forkJoin()

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() 将在发出任何值之前完成所有请求。

【讨论】:

  • 哇,这太棒了,解决了所有问题。我没有意识到 observables 如此强大。谢谢!
【解决方案2】:

如果我理解正确,那么下面的代码应该能让您顺利上路。这将为数组中的每个元素执行一个承诺,一次一个。

        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 的。如果失败,请告诉我。

【讨论】:

    猜你喜欢
    • 2018-04-28
    • 2020-02-19
    • 1970-01-01
    • 2018-03-22
    • 2019-03-31
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 2015-03-31
    相关资源
    最近更新 更多