Moya Task finished with error - code: -999

Created on 26 Feb 2018  路  10Comments  路  Source: Moya/Moya

The version i used is 10.0.1.

While using Moya, coding become more easily. But recently i get a problem when using Moya + Rxswift to a cancellable request. The console print:

2018-02-26 14:15:50.403209+0800 xxx[79866:8080376] Task <6C06B0A5-60A3-4481-B009-5F6F2EA76AF8>.<1> finished with error - code: -999
2018-02-26 14:15:50.453157+0800 xxx[79866:8080373] Task <B5B31D94-F071-4396-9111-B59DB5D7B11E>.<1> finished with error - code: -999
2018-02-26 14:15:50.454108+0800 xxx[79866:8080376] Task <B5B31D94-F071-4396-9111-B59DB5D7B11E>.<1> HTTP load failed (error code: -999 [1:89])

below is my code:

// A variable trigger the network request
var contentType: ContentType? = nil {
    didSet{
        self.bag = DisposeBag()
        self.loadData()
    }
}

// Network request:
func loadData() {
    let provider = MoyaProvider<MainUrl>()
    provider.rx.request(.banner, callbackQueue: DispatchQueue.main)
        .mapJSON()
        .filterData(with: { (results: [[String: Any]]) -> [Model] in
            //transform data
        })
        .subscribe(onSuccess: { (banners) in
            //something to do
        }, onError: { (error) in
            //something todo
        })
        .disposed(by: self.bag)
}

When frequently trigger the network, the above error print in console.

I think this is caused by the provider, which is deallocated when self.bag get a new DisposeBag(). So I create a new member variable to hold this provider. But still get the same error in console.

// Network request:
func loadData() {
    let provider = MoyaProvider<MainUrl>()
    self.provider = provider
    provider.rx.request(.banner, callbackQueue: DispatchQueue.main)
        .mapJSON()
        .filterData(with: { (results: [[String: Any]]) -> [Model] in
            //transform data
        })
        .subscribe(onSuccess: { (banners) in
            //something to do
        }, onError: { (error) in
            //something todo
        })
        .disposed(by: self.bag)
}

What mistake i have made? Could anyone can help me? thank you very much!!!

question rxmoya stale

All 10 comments

@zerozheng It is because you are not retaining your provider. It needs to be at a scope outside of the function definition in order for it to be retained.

Providers.md

Always remember to retain your providers, as they will get deallocated if you fail to do so. Deallocation will return a -999 "canceled" error on response.

@SD10 I define a new member variable which is used to hold the provider in the whole life cycle.

self.provider = provider

but it does't work

@zerozheng Can you show me more of your code? Where are you retaining the provider?

@SD10 thanks for your reply!

below is the code:

import UIKit
import RxSwift
import RxCocoa
import Moya

class MyController: UIViewController {

    var bag = DisposeBag()

    var contentType: Type? = nil {
        didSet{
            self.loadData()
        }
    }

    var provider: AnyObject? = nil

}

private extension MyController {

    func loadData() {

        self.bag = DisposeBag()

        let provider = MoyaProvider<MainUrl>()
        self.provider = provider
        provider.rx.request(MainUrl.banner, callbackQueue: DispatchQueue.main)
            .mapJSON()
            .filterData { (data: [String:Any]) -> [Model] in
                //transform data
            }
            .subscribe(onSuccess: { (result) in
                //something to do with result
            }, onError: { (error) in
                //something to do with error
            })
            .disposed(by: self.bag)
    }
}

Using a variable to hold the provider. It does not work. I think the provider may be deallocated when give a new provider to self.provider self.provider = provider in the loadData() function.
After that, an array, providers, is used to hold all of the providers created. Unfortunately, it doesn't work too. --!

import UIKit
import RxSwift
import RxCocoa
import Moya

class MyController: UIViewController {

    var bag = DisposeBag()

    var contentType: Type? = nil {
        didSet{
            self.loadData()
        }
    }

    var providers: [AnyObject] = []

}

private extension MyController {

    func loadData() {

        self.bag = DisposeBag()

        let provider = MoyaProvider<MainUrl>()
        self.providers.append(provider)
        provider.rx.request(MainUrl.banner, callbackQueue: DispatchQueue.main)
            .mapJSON()
            .filterData { (data: [String:Any]) -> [Model] in
                //transform data
            }
            .subscribe(onSuccess: { (result) in
                //something to do with result
            }, onError: { (error) in
                //something to do with error
            })
            .disposed(by: self.bag)
    }
}

I think the provider may be deallocated when give a new provider to self.provider self.provider = provider in the loadData() function.

@zerozheng Yes, this would cause the provider to be deallocated. I would use 1 provider per TargetType as that is the recommended pattern when using Moya.

Hi, I got the same issue as @zerozheng, moyaProvider got disposed, however when I was tracing the bug in MoyaProvider+Rx.swift by adding print methods

public func request(_ token: Base.Target, callbackQueue: DispatchQueue? = nil) -> Single<Response> {
        return Single.create { [weak base] single in
            print("rx provider base \(base)")
            print("rx provider \(self)")
            let cancellableToken = base?.request(token, callbackQueue: callbackQueue, progress: nil) { result in
                switch result {
                case let .success(response):
                    print(response.description)
                    single(.success(response))
                case let .failure(error):
                    single(.error(error))
                }
            }

            return Disposables.create {
                cancellableToken?.cancel()
            }
        }
    }

It suddenly works without changing anything from my codebase. The issue came back when you remove the print methods.

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

This issue has been marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

This issue has been auto-closed because there hasn't been any activity for at least 21 days. However, we really appreciate your contribution, so thank you for that! 馃檹 Also, feel free to open a new issue if you still experience this problem 馃憤.

@zerozheng Hi, I resolved this problem.
Don't need make the provider to a global var.
Only make the disposeBag to a global var then will run.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Tynox picture Tynox  路  3Comments

cocoatoucher picture cocoatoucher  路  3Comments

dimpiax picture dimpiax  路  3Comments

PlutusCat picture PlutusCat  路  3Comments

hamada147 picture hamada147  路  3Comments