【问题标题】:what is diff b/w Synchronous and asynchronous requests ,How check this operations programmatically什么是 diff b/w 同步和异步请求,如何以编程方式检查此操作
【发布时间】:2016-03-18 04:05:29
【问题描述】:

嗨,我是 ios 的初学者,当我们使用 NSURLRequest 调用服务时,我想知道当我们使用“同步请求”调用服务并以编程方式使用异步请求调用服务时会发生什么, 请以编程方式解释操作,我在下面使用该代码编写了一些代码解释同步和异步操作

我的代码:-

- (void)viewDidLoad {
    [super viewDidLoad];

 NSURL *url = [NSURL URLWithString:@"http://api.kivaws.org/v1/loans/search.json?status=fundraising"];
        NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];

        [theRequest setHTTPMethod:@"GET"];
        [theRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [theRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [theRequest setTimeoutInterval:5];

        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

        if(connection){

            webData = [[NSMutableData alloc] init];
        }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    [webData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    [webData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

    NSLog(@"error is %@",[error localizedDescription]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSString * allDataDictionbary = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];

    NSArray * responseString = [allDataDictionbary JSONValue];

   NSLog(@"final respone dictionary%@",responseString);
   }

【问题讨论】:

  • 重新同步请求和异步请求的区别,见stackoverflow.com/q/21122842/1271826。关于此代码示例,这是一个异步请求,这很好,因为您不想从主线程发出同步请求。事实上,同步网络请求是个糟糕的主意,新的NSURLSession 取代了您在代码示例中使用的已弃用的NSURLConnection,甚至不提供同步再现。
  • 嗨@Rob我是Ios的初学者,你说根本不再使用NSURLConnection。使用 NSURLSession 我该如何使用,请更新我的代码

标签: ios objective-c nsurlconnection


【解决方案1】:

在回答您的问题时,同步请求会阻塞调用它们的线程,直到请求完成。 (因此,通常不鼓励同步请求。)异步请求让当前线程在执行请求时继续执行(例如,继续响应用户与应用程序的交互;响应系统事件等)。这通常是可取的。

您的代码正在执行异步请求(这很好)。不过也有一些问题:

  1. 你不应该再使用NSURLConnection。它已被弃用。使用NSURLSession。它实际上更简单,因为您通常不必编写那些委托方法(除非您想要这样做,因为您有一些迫切需要这样做)。

    有关 NSURLSession 的更多信息,请参阅 URL 会话编程指南中的 Using NSURLSession 或参阅 WWDC 2013 视频 What's New in Foundation Networking 以获得很好的介绍。

  2. 你没有做一些错误处理。您正在检查基本错误(例如,没有网络),这非常好,但您没有考虑其他 Web 服务器错误,这些错误可能并不总是导致 NSError 对象,但可能只是导致 HTTP 状态代码其他超过 200。我建议检查一下。

    请参阅RFC 2616 的第 10 节以获取 HTTP 状态代码列表。

  3. 您正在设置 Content-Typeapplication/json。但这不是 JSON 请求。 (当然,响应是 JSON,但请求不是。)通常你会使用 application/x-www-form-urlencoded 来处理这样的请求。

  4. 在您的代码 sn-p 中,您建议来自服务器的响应是 JSON,其中 NSArray 作为顶级对象。但是顶级对象是NSDictionary

  5. 您正在使用JSONValue。我不确定是哪个 JSON 库,但我们中的许多人只是使用 Apple 提供的内置 NSJSONSerialization 类。很久以前,在 Apple 提供NSJSONSerialization 之前,我们会使用第三方库来解析 JSON,但现在不再需要了。

NSURLSession发送请求的正确方法如下:

NSURL *url = [NSURL URLWithString:@"http://api.kivaws.org/v1/loans/search.json?status=fundraising"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPMethod:@"GET"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (error != nil) {
        NSLog(@"fundamental network error = %@", error);
        return;
    }
    
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
        if (statusCode != 200) {
            NSLog(@"Warning; server should respond with 200 status code, but returned %ld", (long)statusCode);
        }
    }
    
    NSError *parseError;
    NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
    if (responseObject) {
        NSLog(@"responseObject = %@", responseObject);
    } else {
        NSLog(@"Error parsing JSON: %@", parseError);
        NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"responseString = %@", responseString);
    }
}];
[task resume];

// Note, you'll reach this portion of your code before the
// above `completionHandler` runs because this request runs
// asynchronously. So put code that uses the network response
// above, inside that `completionHandler`, not here.

【讨论】:

  • 因为我在我的应用程序中使用了 JSONValue,所以我使用了第三方库,即 SBJSON 库
  • 还有很多人说使用 NSJSONSerialization 只是为了获取小数据,为了更好地获取大量数据,最好使用 SBJSO N,@Rob 正确吗?
  • 没关系,如果你真的想用它也没关系。我只是指出我们不再需要使用那些第三方库来解析 JSON。但是,如果您有很多代码,依赖于该库,请随时继续使用它,如果必须的话。关于 JSON 解析的速度,这个 JSON 肯定不够大,不会有任何实质性差异。我个人总是尽量减少第三方代码的存在,将其限制在提供显着好处的代码上,恕我直言,这里不是这种情况。
  • ok @Rob 我买了一个小东西,如何使用 NSURLSession 发布数据假设我有类似 (NSDictionary *mainDict = [NSDictionary dictionaryWithObjectsAndKeys: @"123" ,@"medicaId",@"something ",@"密码", nil];)
  • 我想我必须在这里使用 POST 方法,但我不知道如何使用 NSUrlSEssion 发送数据,你能解释一下吗
【解决方案2】:

当从线程发起 HTTP 请求时,如果您不介意耐心等待(“感谢您的等待”),该线程可以决定自行处理您的响应。该线程被阻塞,直到 HTTP 请求被完全处理。或者,线程可以认为他有更好的事情要做,而不是等待一个冗长的 HTTP 事务,因此他很高兴地将任务传递给另一个进程来处理 HTTP 事务,并带有一个回调,以便他们可以保持联系。当其他进程完成时,它会使用回调通知它的发起者它已经完成。

【讨论】:

    【解决方案3】:

    把它想象成一条路。想象一下,如果没有被告知,您的应用程序将只在一条道路上运行。现在,您的应用程序中发生的一切都必须保持在这条路上。如果任何“汽车”(阅读:任务)花费的时间太长,整个事情都会关闭,并且您的“道路”(阅读:应用程序)变得无响应。在异步操作中,您创建另一条道路(读取:线程)并且缓慢行驶的汽车可以切换到该道路。一旦它的速度足以在主干道上运行,它就可以切换回主干道。

    【讨论】:

    • 我要求以编程方式解释我,这就是我发布一些代码的原因
    【解决方案4】:

    同步请求阻塞线程直到它完成。而异步请求创建单独的线程并执行,完成后返回主线程。

    当你运行这条线时,会有 1 秒的时间差异或取决于网速

     NSLog(@"before SynchronousRequest time %@",[NSDate date]);
        NSError *error = nil;
        NSHTTPURLResponse *response = nil;
        NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response   error:&error];
        NSLog(@"after SynchronousRequest time %@",[NSDate date]);
    

    在 SynchronousRequest 时间 2015-12-12 09:26:01 +0000 之前

    在 SynchronousRequest 时间 2015-12-12 09:26:02 +0000 之后

    当你运行这条线时,没有时间差异

     NSLog(@"before AsynchronousRequest time %@",[NSDate date]);
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            if (data) {
                NSString *str = [[NSString alloc] initWithData:data
                                                     encoding:NSUTF8StringEncoding];  // note the retain count here.
                NSLog(@"%@",str);
            } else {
                // handle error
            }
        }];
        NSLog(@"after AsynchronousRequest time %@",[NSDate date]);
    

    在 AsynchronousRequest 时间 2015-12-12 09:29:50 +0000 之前

    在 AsynchronousRequest 时间 2015-12-12 09:29:50 +0000 之后

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多