代码之家  ›  专栏  ›  技术社区  ›  Chen Li Yong

如何在swift中按顺序执行大量的网络呼叫?

  •  1
  • Chen Li Yong  · 技术社区  · 6 年前

    例如,我有一个URL数组来获取JSON数据。列表计数可以达到数千。我有一个循环从每个元素中检索JSON数据并不重要。

    let urls : [URL] = getUrls();
    var results = [String: Dictionary]();
    
    for url in url {
        networkRequest (url: url, callback: { json in
            results[url.absoluteString] = json;
        });
    }
    

    问题是所有这些请求都是在并发时间内发出的,所以结果要么运行得非常慢,要么部分丢失。

    所以我认为这是因为请求在同一时间运行得太多了。所以我想添加一些运行的网络呼叫配额。

    let urls : [URL] = getUrls();
    var results = [String: Dictionary]();
    var quota = 0;
    
    for url in url {
        quota += 1;
        while quota > 5 { }
        networkRequest (url: url, callback: { json in
            quota -= 1;
            results[url.absoluteString] = json;
        });
    }
    

    使用打印的控制台消息,我可以看到前5个网络调用转到networkrequest函数,但从未返回任何数据。从未回过电话。我应该如何实现这个配额调用?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Shehata Gamal    6 年前

    您可以尝试创建串行队列

    let que = DispatchQueue(label: "custQ") 
    for url in urls {
      que.sync {
        quota += 1;
        while quota > 5 { }
        networkRequest (url: url, callback: { json in
            quota -= 1
            results[url.absoluteString] = json
        })
        }
    
    }
    

    但注意 networkRequest 应该在同一个队列线程中运行,不要调度它,或者递归地调用它

    var counter = 0
    func callUrl(_ url:URL) {
        quota += 1;
        while quota > 5 { }
        networkRequest (url: url, callback: { json in
            self.quota -= 1
            self.results[url.absoluteString] = json
            self.counter +=1
            if self.counter < 20 {  /// or set any number 
              self.callUrl(urls[counter])
            }
        })
    
    }