Как выполнить множество сетевых вызовов последовательно в Swift? - PullRequest
0 голосов
/ 22 октября 2018

Например, у меня есть массив 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 Ответ

0 голосов
/ 22 октября 2018

Вы можете попытаться создать последовательную очередь

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])
        }
    })

}
...