Tôi đang cố gắng xây dựng một lớp quản lý các cuộc gọi mạng cho dự án của mình. Đến thời điểm này, tôi có nghĩa là xử lý lỗi trên toàn cầu, mọi thứ đều ổn. Tôi đã tạo ra hai chức năng; đối với yêu cầu gửi bài đăng postRequest(:_)
và để nhận yêu cầu getRequests(:_)
. Datamaker có chức năng trả về dữ liệu như URL, tham số, tiêu đề, vv, các hàm dataparser để phân tích cú pháp phản hồi và cuối cùng là một hàm để giải quyết các lỗi được gọi là errorHandler()
.Alamofire: Làm thế nào để xử lý 401 toàn cầu?
Khi tôi gọi một hàm yêu cầu, tôi cung cấp thông số để giúp chức năng yêu cầu. Trong hàm, nó gọi các nhà lập trình để lấy dữ liệu trước hết, sau đó yêu cầu với Alamofire
và cuối cùng nếu yêu cầu thành công, nó gọi dataparser và onSuccess(data:)
đóng hoặc nếu nó không phải là yêu cầu errorHandler(statusCode:)
và onFailure(message:)
đóng.
Tôi đặt khối chuyển đổi trong errorHandler
và đã cung cấp mã trạng thái cho thông số của nó. Trong số case 401
Tôi gọi là Token().refresh()
và hoàn thành được gọi là hoàn thành errorHanlder
. Trong khối hoàn thành của postRequest
/errorHandler
, tôi gọi lại là postRequest
với cùng thông số. Nó không hoạt động. Tôi không lý do tại sao, nó đã đi vào vòng lặp vô hạn mọi lúc và yêu cầu liên tục.
Vì vậy, tôi quyết định thử cnoon 's AuthorizationManager
lớp (có thể được tìm thấy trong liên kết này; Alamofire : How to handle errors globally). Tôi đã thay đổi nó một chút (thêm thông số mới làm tiêu đề và thay đổi loại của NetworkSuccessHandler
thành NSData
). Dưới đây là hình thức mới:
public class AuthorizationManager: Manager {
public typealias NetworkSuccessHandler = (NSData?) -> Void
public typealias NetworkFailureHandler = (NSHTTPURLResponse?, AnyObject?, NSError) -> Void
private typealias CachedTask = (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void
private var cachedTasks = Array<CachedTask>()
private var isRefreshing = false
public func startRequest(
method method: Alamofire.Method,
URLString: URLStringConvertible,
parameters: [String: AnyObject]?,
encoding: ParameterEncoding,
headers: [String:String]?,
success: NetworkSuccessHandler?,
failure: NetworkFailureHandler?) -> Request?
{
let cachedTask: CachedTask = { [weak self] URLResponse, data, error in
guard let strongSelf = self else { return }
if let error = error {
failure?(URLResponse, data, error)
} else {
strongSelf.startRequest(
method: method,
URLString: URLString,
parameters: parameters,
encoding: encoding,
headers: headers,
success: success,
failure: failure
)
}
}
if self.isRefreshing {
self.cachedTasks.append(cachedTask)
return nil
}
// Append your auth tokens here to your parameters
let request = self.request(method, URLString, parameters: parameters, encoding: encoding, headers: headers)
request.response { [weak self] request, response, data, error in
guard let strongSelf = self else { return }
if let response = response where response.statusCode == 401 {
strongSelf.cachedTasks.append(cachedTask)
strongSelf.refreshTokens()
return
}
if let error = error {
failure?(response, data, error)
} else {
success?(data)
}
}
return request
}
func refreshTokens() {
self.isRefreshing = true
// Make the refresh call and run the following in the success closure to restart the cached tasks
Token().refresh {() ->() in
let cachedTaskCopy = self.cachedTasks
self.cachedTasks.removeAll()
cachedTaskCopy.map { $0(nil, nil, nil) }
self.isRefreshing = false
}
}
}
gọi nó trong tôi postRequest
như:
func postRequest(requestType: postRequestType, additionalParameters: [String]?, onSuccess: onSuccessRequest = {_ in }, onFailure: onFailureRequest = {_ in }){
print("post")
let requestData = returnStaticDataForPostRequest(requestType, additionalParameters: additionalParameters)
let Manager = AuthorizationManager()
Manager.startRequest(method: .POST, URLString: requestData.0, parameters: requestData.2, encoding: requestData.3, headers: requestData.1, success: { (data) -> Void in
print("Manager")
let json = JSON(data: data!)
print(json)
dataParserForPostRequests(json, parseForWhat: requestType)
onSuccess(json: json)
}) { (response, message, error) -> Void in
print(error)
}
}
Và sử dụng postRequests
trong ViewController
:
postRequest(.LOGIN, additionalParameters: ["asdasd", "asdasd"], onSuccess: { (json) ->() in
print(">>>login_try_succeeded")
self.performSegueWithIdentifier("LoginToMain", sender: self)
}) { (errorCode) ->() in
print(">>>login_try_failed(\(errorCode))")
}
Đây là trạng thái hiện tại. Khi tôi chạy mã và cố gắng đăng nhập AuthorizationManager
không hoạt động. Nó chỉ in;
post
Và cuối cùng, tôi không biết nếu nó có liên quan nhưng có cảnh báo màu vàng tại dòng này:
cachedTaskCopy.map { $0(nil, nil, nil) }
nói "Result of call to 'map' is unused"
Tóm lại tôi cần phải tìm ra cách tôi có thể xử lý 401 và tôi biết cách sử dụng AuthorizationManager
theo cách khác.
EDIT:
Tôi cố gắng chạy mã này trực tiếp từ ViewController
nhưng nó không làm việc ở tất cả. Nó giống như mã là vô hình.
AuthorizationManager().startRequest(method: .POST, URLString: NSURL(string: "http://server.url/token")!, parameters: ["":""], encoding: .JSON,headers: ["":""], success: { (data) -> Void in
print(data)
}) { (response, data, error) -> Void in
print(error)
print("asdasd")
}
Đó không phải là câu hỏi của tôi nhưng câu trả lời của bạn sẽ thực sự hoạt động cho phần cuối được giải thích là 'EDIT' (hoặc tôi không nhớ câu hỏi của tôi là gì :)). Dù sao, vì đã có rất nhiều thời gian trôi qua kể từ khi tôi hỏi điều này, tôi đã bắt đầu sử dụng Moya (https://github.com/Moya/Moya) cung cấp các tính năng thực sự tốt đẹp để phát triển việc sử dụng sạch Alamofire. Nó được thảo luận làm thế nào để xử lý 401, và các mã trạng thái khác, trong liên kết này; https://github.com/Moya/Moya/issues/379. Tuy nhiên có vẻ như câu trả lời của bạn là nhận được upvotes, tôi cho rằng nó rất hữu ích cho mọi người. Vì vậy, tôi sẽ chấp nhận điều này. – Faruk
Vâng, hy vọng nó sẽ giúp một ai đó! Ngoài ra, Moya là tuyệt vời, vui mừng bạn đã có thể tìm ra một giải pháp. – tbogosia
Vâng! Cảm ơn bạn đã quan tâm giúp :) – Faruk