使用 PromiseKit 强制顺序下载
Using PromiseKit to force sequential download
我正在使用 PromiseKit 并想强制顺序下载 JSON。 JSON 的数量可能会改变。
我已阅读 this 关于链接的内容。
如果我的下载次数是固定的,比如 3 次,那就没问题了。
但是,如果我想按顺序下载不断变化的下载次数怎么办?
这是我的 2 个网址代码。我想知道如何通过对数组进行 dateUrlArray[i]
迭代来做到这一点?
- (void)downloadJSONWithPromiseKitDateArray:(NSMutableArray *)dateUrlArray {
[self.operationManager GET:dateUrlArray[0]
parameters:nil]
.then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;
Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
return [self.operationManager GET:dateUrlArray[1]
parameters:nil];
}).then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;
Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
})
.catch(^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self handleCatchwithError:error];
});
}).finally(^{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogInfo(@".....finally");
});
});
}
您正在寻找的概念是then
可链接。你想在一个 for 循环中链接多个 promise。
我的 Objective-C 真的很生锈 - 但它应该看起来像:
// create an array for the results
__block NSMutableArray *results = [NSMutableArray arrayWithCapacity:[urls count]];
// create an initial promise
PMKPromise *p = [PMKPromise promiseWithValue: nil]; // create empty promise
for (id url in urls) {
// chain
p = p.then(^{
// chain the request and storate
return [self.operationManager GET:url
parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation) {
[results addObject:responseObject]; // reference to result
return nil;
});
});
}
p.then(^{
// all results available here
});
对于我们这些正在寻找 Swift 2.3 解决方案的人:
import PromiseKit
extension Promise {
static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? {
return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in
return fn1?.then({ (_) -> Promise<T> in
return fn2!()
}) ?? fn2!()
}
}
}
注意这个函数 returns nil
如果 promises 数组是空的。
使用示例
下面是一个如何按顺序上传附件数组的例子:
func uploadAttachments(attachments: [Attachment]) -> Promise<Void> {
let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in
return {
return self.uploadAttachment(attachment)
}
})
return Promise.resolveSequentially(promiseFns)?.then({}) ?? Promise()
}
func uploadAttachment(attachment: Attachment) -> Promise<Void> {
// Do the actual uploading
return Promise()
}
感谢 Vegard 的回答,我重写了 Swift 3:
extension Promise {
static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? {
return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in
return fn1?.then{ (_) -> Promise<T> in
return fn2!()
} ?? fn2!()
}
}
}
/* Example */
func uploadAttachments(_ attachments: [Attachment]) -> Promise<Void> {
let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in
return {
return self. uploadAttachment(attachment)
}
})
return Promise.resolveSequentially(promiseFns: promiseFns)?.then{Void -> Void in} ?? Promise { Void -> Void in }
}
我正在使用 PromiseKit 并想强制顺序下载 JSON。 JSON 的数量可能会改变。
我已阅读 this 关于链接的内容。 如果我的下载次数是固定的,比如 3 次,那就没问题了。
但是,如果我想按顺序下载不断变化的下载次数怎么办?
这是我的 2 个网址代码。我想知道如何通过对数组进行 dateUrlArray[i]
迭代来做到这一点?
- (void)downloadJSONWithPromiseKitDateArray:(NSMutableArray *)dateUrlArray {
[self.operationManager GET:dateUrlArray[0]
parameters:nil]
.then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;
Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
return [self.operationManager GET:dateUrlArray[1]
parameters:nil];
}).then(^(id responseObject, AFHTTPRequestOperation *operation) {
NSDictionary *resultDictionary = (NSDictionary *) responseObject;
Menu *menu = [JsonMapper mapMenuFromDictionary:resultDictionary];
if (menu) {
[[DataAccess instance] addMenuToRealm:menu];
}
})
.catch(^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self handleCatchwithError:error];
});
}).finally(^{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogInfo(@".....finally");
});
});
}
您正在寻找的概念是then
可链接。你想在一个 for 循环中链接多个 promise。
我的 Objective-C 真的很生锈 - 但它应该看起来像:
// create an array for the results
__block NSMutableArray *results = [NSMutableArray arrayWithCapacity:[urls count]];
// create an initial promise
PMKPromise *p = [PMKPromise promiseWithValue: nil]; // create empty promise
for (id url in urls) {
// chain
p = p.then(^{
// chain the request and storate
return [self.operationManager GET:url
parameters:nil].then(^(id responseObject, AFHTTPRequestOperation *operation) {
[results addObject:responseObject]; // reference to result
return nil;
});
});
}
p.then(^{
// all results available here
});
对于我们这些正在寻找 Swift 2.3 解决方案的人:
import PromiseKit
extension Promise {
static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? {
return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in
return fn1?.then({ (_) -> Promise<T> in
return fn2!()
}) ?? fn2!()
}
}
}
注意这个函数 returns nil
如果 promises 数组是空的。
使用示例
下面是一个如何按顺序上传附件数组的例子:
func uploadAttachments(attachments: [Attachment]) -> Promise<Void> {
let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in
return {
return self.uploadAttachment(attachment)
}
})
return Promise.resolveSequentially(promiseFns)?.then({}) ?? Promise()
}
func uploadAttachment(attachment: Attachment) -> Promise<Void> {
// Do the actual uploading
return Promise()
}
感谢 Vegard 的回答,我重写了 Swift 3:
extension Promise {
static func resolveSequentially(promiseFns: [()->Promise<T>]) -> Promise<T>? {
return promiseFns.reduce(nil) { (fn1: Promise<T>?, fn2: (()->Promise<T>)?) -> Promise<T>? in
return fn1?.then{ (_) -> Promise<T> in
return fn2!()
} ?? fn2!()
}
}
}
/* Example */
func uploadAttachments(_ attachments: [Attachment]) -> Promise<Void> {
let promiseFns = attachments.map({ (attachment: Attachment) -> (()->Promise<Void>) in
return {
return self. uploadAttachment(attachment)
}
})
return Promise.resolveSequentially(promiseFns: promiseFns)?.then{Void -> Void in} ?? Promise { Void -> Void in }
}