OC中对Promise的简单实现
2020-03-26 本文已影响0人
哆啦_
对前端熟悉的小伙伴们都知道,ES6之后有一个Promise
的东西,是异步编程的一种解决方案。可以很方便的进行异步编程
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 2000);
}).then(res => {
}).catch(err => {
})
异步任务结束之后将会执行then
或者catch
函数。在then
中我们会处理业务数据,而在catch
对错误进行统一处理
相类似的,Flutter
中提供了Future
来实现相似的功能(Dart库中有很多返回Future
的函数)。
dio.get(url, queryParameters:parameter).then((resp){
// 请求成功
log(resp.data);
}).catchError((err){
// 出现错误
log(err);
});
在iOS中的简单实现
首先是要实现链式调用,在iOS中有很多优秀的第三方库都采用了链式调用,比如大名鼎鼎的Masonry
。
链式调用的关键是每次调用结束之后都把对象本身返回,这样可以一直调用下去。
- (Promise *)fun1
{
// do something
return self;
}
- (Promise *)fun2
{
// do something
return self;
}
[Promise new].fun1.fun2;
[[[Promise new] fun1] fun2];
为了能在then
中处理网络请求返回的数据,且使用点语法来调用then
,需要把数据回调暴露给调用者,并把then
声明为属性。
@class Promise;
typedef void (^WYAPISuccessCallBack)( NSString * _Nullable message, id _Nullable data);
typedef void (^WYAPIFailCallBack)( NSError * _Nullable error, NSString * _Nullable message);
typedef Promise *_Nullable(^WYPromiseThen)(WYAPISuccessCallBack then);
typedef Promise *_Nullable(^WYPromiseCatch)(WYAPIFailCallBack catchError);
@interface Promise : NSObject
@property (nonatomic , copy , readonly) WYPromiseThen then;
@property (nonatomic , copy , readonly) WYPromiseCatch catchError;
- (Promise *)POST:(NSString *)url
param:(NSDictionary *)param;
@end
接下来就是对属性的实现,我们把传入进来的block进行保存,在网络请求结束之后回调该block
@interface Promise ()
@property (nonatomic, copy) WYAPISuccessCallBack success;
@property (nonatomic, copy) WYAPIFailCallBack fail;
@end
@implementation Promise
- (WYPromiseThen)then
{
__weak typeof(self)weakSelf = self;
return ^(WYAPISuccessCallBack value) {
// 保存成功的回调
weakSelf.success = value;
return weakSelf;
};
}
- (WYPromiseCatch)catchError
{
__weak typeof(self)weakSelf = self;
return ^(WYAPIFailCallBack value) {
weakSelf.fail = value;
return weakSelf;
};
}
- (Promise *)POST:(NSString *)url
param:(NSDictionary *)param
{
[Promise PostUrlString:url params:param success:self.success fail:self.fail];
return self;
}
+ (AFHTTPSessionManager *)sharedManager {
static AFHTTPSessionManager *httpSessionManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
httpSessionManager = [AFHTTPSessionManager manager];
httpSessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
httpSessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
httpSessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", @"text/javascript", @"text/json", @"text/html", nil];
});
return httpSessionManager;
}
+ (NSURLSessionDataTask *)PostUrlString:(NSString *)urlString
params:(id)params success:(WYAPISuccessCallBack)success
fail:(WYAPIFailCallBack)fail
{
AFHTTPSessionManager *manager = [self sharedManager];
NSURLSessionDataTask *task = [manager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *data = nil;
if([responseObject isKindOfClass:[NSData class]]){
NSData *responseData = (NSData *)responseObject;
data = [NSJSONSerialization JSONObjectWithData:responseData
options:0
error:nil];
} else if ([responseObject isKindOfClass:[NSDictionary class]]){
data = responseObject;
}
// 这里对返回数据进行统一处理 不同项目可能返回内容不同
NSString *message = [data objectForKey:@"msg"];
BOOL result = [[data objectForKey:@"result"] boolValue];
if (result) {
if (success) {
success(message, data[@"data"]);
}
} else {
if (fail) {
fail(nil, message);
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
fail(error, nil);
}];
return task;
}
接下来就是调用了
NSDictionary *param = @{};
NSString *url = @"";
// 不处理回调
[[Promise new] POST:url param:param];
// 只处理成功的回调
[[Promise new] POST:url param:param].then(^(NSString * _Nullable message, id _Nullable data) {
});
// 处理成功&失败的回调
[[Promise new] POST:url param:param].then(^(NSString * _Nonnull message, id _Nonnull data) {
}).catchError(^(NSError * _Nonnull error, NSString * _Nonnull message) {
});
这个是今天心血来潮,想看下前端Promise在iOS上会是怎样的效果,所以简单的实现一下,没什么技术难点。