执行异步任务的轮询请求

时间:2017-05-16 12:43:19

标签: ios swift swift3 system.reactive rx-swift

我已经编写了一个Rx查询来在计时器中执行异步任务。这也处理我需要丢弃其响应稍后的订单请求的场景。这是用C#编写的:

public static IObservable<T> PollingAync<T> (Func<Task<T>> AsyncCall, double TimerDuration)
        {
            return Observable
         .Create<T>(o =>
         {
             var z = 0L;
             return
                 Observable
                     .Timer(TimeSpan.Zero, TimeSpan.FromSeconds(TimerDuration))
                     .SelectMany(nr =>
                         Observable.FromAsync<T>(AsyncCall),
                         (nr, obj) => new { nr, obj})
                     .Do(res => z = Math.Max(z, res.nr))
                     .Where(res => res.nr >= z)
                     .Select(res => res.obj)
                     .Subscribe(o);
         });

    }

我希望在swift中编写相同的实现来处理异步任务,并且还丢弃其响应稍后的订单请求。我想在swift3.0中写这个

由于我是swift的新手,请帮助告诉我如何在不使用Rx 的快速中获得相同的结果。

1 个答案:

答案 0 :(得分:2)

这是一个有趣的问题要回答......

enum Result<T> {
    case success(T)
    case failure(Error)
}

typealias Cancel = () -> Void

func pollingAsync<T>(asyncCall: @escaping (@escaping (Result<T>) -> Void) -> Cancel, duration: TimeInterval, callback: @escaping (Result<T>) -> Void) -> Cancel {
    let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main)

    timer.scheduleRepeating(deadline: .now(), interval: .milliseconds(Int(duration * 1000)), leeway: .milliseconds(10))

    var asyncCallCancel: Cancel? = nil
    timer.setEventHandler {
        asyncCallCancel?()
        asyncCallCancel = asyncCall {
            callback($0)
        }
    }
    timer.resume()
    return {
        asyncCallCancel?()
        timer.cancel()
    }
}

要使用上述内容,您可以执行以下操作:

let cancel = pollingAsync(asyncCall: myAsyncOp, duration: 2.0) {
    print($0)
}

如果您忘记了从此功能返回的Cancel对象,您将无法关闭计时器。

作为参考,这是RxSwift中的等效代码:

func pollingAsync<T>(asyncCall: @escaping () -> Observable<T>, duration: TimeInterval) -> Observable<Event<T>> {
    return Observable<Int>.interval(duration, scheduler: MainScheduler.instance)
        .flatMapLatest { _ in
            asyncCall().materialize().filter { !$0.isCompleted }
    }
}