【问题标题】:long running REST API长时间运行的 REST API
【发布时间】:2013-05-04 10:21:27
【问题描述】:

我需要连接的后端 API 大约需要 3-4 分钟才能返回响应。 iOS 客户端似乎正好在 60 秒时超时(这是默认值),我不知道如何延长该超时时间。

我尝试将 NSURLRequest 的 timeoutInterval 设置为一个较大的数字,并设置 Connection: Keep-Alive 标头,但我没有运气。这是我正在使用的代码,省略了一些 API 细节:

NSURL *url = [NSURL URLWithString:@"myAPI"];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPMethod:@"POST"];

NSString *postString = @"key1=val1&key2=val2...";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

request.timeoutInterval = 600.0f;

[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     NSLog(@"data = %@", data);
}];

即使后端 API 仍在处理请求,也不返回任何数据并且所有响应头字段都为空。

我听说我可能需要设置一个称为“socketTimout”间隔的东西,以便套接字知道保持连接打开更长时间,但我不知道在哪里设置。

【问题讨论】:

  • 您确定服务器上的超时时间足够大吗?

标签: iphone ios objective-c cocoa-touch


【解决方案1】:

您是否尝试过使用 NSURLConnection 委托方法而不是 sendAsynchronousRequest

通过使用:

NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];

您可以监视委托方法didReceiveData 并将传入的数据附加到 NSMutableData 的实例:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.data appendData:data];
}

这样,至少你会知道你正在接收数据,你甚至可以向你的用户展示一个进度条或其他东西。

【讨论】:

  • 我可以试试,但同时没有数据发送。这需要很长时间不是因为它正在下载文件,而是因为服务器正在进行繁重的处理。完成后,它会返回一个简单的 JSON 响应,由于超时太早,应用程序没有收到该响应。
  • 哇哦。这是一个有趣的现象。安德鲁的回答是一个很好的建议。与其强迫 iPhone 等待服务器的处理,不如建立多个 API 调用来启动该过程,并查询它的完成状态。另一个建议是在您的服务器上设置一个定期执行此过程的 cron 作业。这样,当 iPhone 准备好接收数据时,服务器可以只返回该过程的最新结果,而不是在那个时候执行该过程。
【解决方案2】:

Erik,查看这篇文章的答案:

NSURLConnection timeout?

基本上你在NSURLRequest上使用这个方法

requestWithURL:cachePolicy:timeoutInterval:

【讨论】:

    【解决方案3】:

    与其尝试延长超时时间,不如稍微修改一下您的服务器架构。让服务器在获得所有数据后立即返回 200 OK,然后在后台队列中完成处理。创建另一个 API 调用,您可以使用它来检索数据并让 iOS 应用程序定期检查以查看数据是否已被处理。或者,使用推送通知让用户/手机知道数据何时完成处理。

    如果您碰巧使用的是 Ruby on Rails,那么将长时间运行的进程设置为在工作线程上发生是非常容易的。看看delayed_job Ruby gem。

    如果由于某种原因您无法修改服务器的运行方式,请尝试确保您使用的 API 本身没有设置超时。我想不出 iOS 会忽略您设置的 timeoutInterval 的原因,除非该属性是只读的。尝试改用这个 init 方法:

    - initWithURL:cachePolicy:timeoutInterval:
    

    【讨论】:

      猜你喜欢
      • 2019-05-07
      • 2016-01-05
      • 2020-02-20
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 2018-01-30
      相关资源
      最近更新 更多