【问题标题】:Swift PromiseKit: Equivalent to when() which executes sequentially?Swift PromiseKit:相当于顺序执行的when()?
【发布时间】:2018-06-29 05:42:43
【问题描述】:

我正在使用 PromiseKit 和 Swift,到目前为止它非常方便。他们提供的功能之一是when(),它允许您拥有一个包含任意数量的承诺的数组,并且只有在所有承诺都完成后才执行某些事情。

但是,数组中的 Promise 是并行执行的。我还没有找到任何可以让我按顺序执行它们的功能。我尝试编写自己的递归函数,但它似乎没有按照它们在数组中的顺序执行承诺,并且我偶尔会遇到“Promise deallocated”错误。请帮忙!

static func executeSequentially(promises: [Promise<Void>]) -> Promise<Void> {
    return Promise<Void> { fulfil, reject in
        var mutablePromises = promises
        if mutablePromises.count > 0 {
            mutablePromises.first!
                .then { _ -> Promise<Void> in
                    print("DEBUG: \(mutablePromises.count) promises in promise array.")
                    mutablePromises.remove(at: 0)
                    return executeSequentially(promises: mutablePromises)
                }.catch { error in
                    print("DEBUG: Promise chain rejected.")
                    reject(error)
            }
        } else {
            print("DEBUG: Promise chain fulfilled.")
            fulfil(())
        }
    }
}

【问题讨论】:

    标签: ios swift promisekit


    【解决方案1】:

    您可以使用when(fulfilled: array.makeIterator(), concurrently: 1)。 示例:

    var intGenerator = (1...10).makeIterator()
    var current = 0
    
    func log(_ msg: String) {
        let ts = Date().description
        print("\(ts): \(msg)")
    }
    
    let generator = AnyIterator<Promise<Void>> {
        guard let i = intGenerator.next() else {
            return nil
        }
        log("Doing \(i)")
        return after(.seconds(1)).done {
            log("Done \(i)")
            current = i
        }
    }
    
    log("Start")
    when(fulfilled: generator, concurrently: 1).done { _ in
        log("Finish")
    }
    

    来源:https://github.com/mxcl/PromiseKit/issues/1093

    我只是简单地封装了它。

       func chainSerially<T, S>(_ datas: [T],_ iteratorHandle: @escaping (T) -> Promise<S>?) -> Promise<[S]> {
            var generator = datas.makeIterator()
            let iterator = AnyIterator<Promise<S>> {
                guard let next = generator.next() else {
                    return nil
                }
                return iteratorHandle(next)
            }
            
            return when(fulfilled: iterator, concurrently: 1)
        }
    

    使用:

        func log(_ msg: String) {
            let ts = Date().description
            print("\(ts): \(msg)")
        }
        
        
        func test() {
            log("start")
            chainSerially(Array(1...10)) { (value: Int?) -> Promise<Void>? in
                guard let value = value else {return nil}
    
                log("Doing \(value)")
                return after(.seconds(1)).done {
                    log("done \(value)")
                }
            }.done { _ in
                print("end")
            }
    
        }
    
    logs:
    2021-10-09 02:01:43 +0000: start
    2021-10-09 02:01:43 +0000: Doing 1
    2021-10-09 02:01:44 +0000: done 1
    2021-10-09 02:01:44 +0000: Doing 2
    2021-10-09 02:01:45 +0000: done 2
    2021-10-09 02:01:45 +0000: Doing 3
    2021-10-09 02:01:46 +0000: done 3
    2021-10-09 02:01:46 +0000: Doing 4
    2021-10-09 02:01:47 +0000: done 4
    2021-10-09 02:01:47 +0000: Doing 5
    2021-10-09 02:01:48 +0000: done 5
    2021-10-09 02:01:48 +0000: Doing 6
    2021-10-09 02:01:50 +0000: done 6
    2021-10-09 02:01:50 +0000: Doing 7
    2021-10-09 02:01:51 +0000: done 7
    2021-10-09 02:01:51 +0000: Doing 8
    2021-10-09 02:01:52 +0000: done 8
    2021-10-09 02:01:52 +0000: Doing 9
    2021-10-09 02:01:53 +0000: done 9
    2021-10-09 02:01:53 +0000: Doing 10
    2021-10-09 02:01:54 +0000: done 10
    end
    
    

    如果要串行,并发必须为1

    【讨论】:

      【解决方案2】:

      这是一个扩展,它接受一组 Promise 并返回一个新的 Promise,其中所有单独的 Promise 链接在一起以串行运行。我已经修改了此处找到的版本以与 Swift 5 / PromiseKit 7 alpha 一起使用:https://gist.github.com/kashifshaikh/416b9ffbd300eb680fad3641b6ec53ea

      原作者随附的帖子可以在这里找到:https://medium.com/@peatiscoding/promisekit-chaining-3c957a8ace24

      import Foundation
      import PromiseKit
      
      extension Promise {
        
        /// Returns a single Promise that you can chain to. Wraps the chains of promises passed into the array into a serial promise to execute one after another using `promise1.then { promise2 }.then ...`
        ///
        /// - Parameter promisesToExecuteSerially: promises to stitch together with `.then` and execute serially
        /// - Returns: returns an array of results from all promises
        public static func chainSerially<T>(_ promises:[() -> Promise<T>]) -> Promise<[T]> {
          // Return a single promise that is fullfilled when
          // all passed promises in the array are fullfilled serially
          return Promise<[T]> { seal in
            var outResults = [T]()
            
            if promises.count == 0 {
              seal.fulfill(outResults)
            } else {
              let finalPromise:Promise<T>? = promises.reduce(nil) { (r, n) -> Promise<T> in
                return r?.then { promiseResult -> Promise<T> in
                  outResults.append(promiseResult)
                  return n()
                } ?? n()
              }
              
              finalPromise?.done { result in
                outResults.append(result)
                
                seal.fulfill(outResults)
              }.catch { error in
                seal.reject(error)
              }
            }
          }
        }
      }
      

      【讨论】:

      猜你喜欢
      • 2021-09-22
      • 2014-08-23
      • 2010-09-15
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      相关资源
      最近更新 更多