2016-11-16 72 views
1

我試圖做到這一點看似瑣碎的事情返回一個承諾:從PromiseKit/Alamofire

static func list() -> Promise<[Activity]> { 
    let endpoint = "\(self.baseUrl)/v1/activities" 

    return Promise { fulfill, reject in 
     self.fetchHeaders { (headers) in 
      return Alamofire.request(
       endpoint, 
       method: .get, 
       parameters: nil, 
       encoding: JSONEncoding.default, 
       headers: headers 
      ).validate().responseJSON().then() { response in 
       guard let json = response as? JSON else { 
        reject(ActivityError.parse("Malformed JSON")) 
       } 

       guard let jsonActivities = json["activities"] as? [JSON] else { 
        reject(ActivityError.parse("Missing field")) 
       } 

       var activities: [Activity] = [] 

       for jsonActivity in jsonActivities { 
        guard let activity = Activity(json: jsonActivity) else { 
         reject(ActivityError.parse("Unable to parse an Activity object")) 
        } 

        activities.append(activity) 
       } 

       fulfill(activities) 
      }.catch { error in 
       reject(ActivityError.network("HTTP response failure")) 
      } 
     } 
    } 
} 

然而,編譯器(理所當然)抱怨說:

'後衛的身體可能不告吹,可以考慮使用「迴歸」或「休息」 退出範圍

我明白我需要回報這裏有個承諾。我只是無法弄清楚在reject()和fulfill()調用下放什麼。

回答

6

rejectfulfill調用沒有任何問題。問題是,當你rejectguard語句,你還必須return退出關閉:

guard let json = response as? JSON else { 
    reject(ActivityError.parse("Malformed JSON")) 
    return 
} 

guard let jsonActivities = json["activities"] as? [JSON] else { 
    reject(ActivityError.parse("Missing field")) 
    return 
} 

關鍵的一點是,你不想混爲一談由該方法返回的承諾(這後來被fulfillreject滿足),事實上在這個關閉中,您必須立即退出關閉,guard條款中的return


我不能重現此問題與您的代碼(因爲你還沒有提供MCVE這裏有引用,我解決不了)。但這裏是你的代碼的說明使用guard簡化翻譯:

所以,如果不使用PromiseKit/Alamofire,你可以這樣做:

func list() -> Promise<[String: Any]> { 
    return Promise { fulfill, reject in 
     Alamofire.request(url) 
      .validate() 
      .responseJSON { response in 
       switch response.result { 
       case .success(let json): 
        guard let dictionary = json as? [String: Any] else { 
         reject(ActivityError.malformed("not a dictionary")) 
         return 
        } 
        fulfill(dictionary) 
       case .failure(let error): 
        reject(error) 
       } 
     } 
    } 
} 

正如你所看到的,你是返回一個Promise,但在Alamofire封閉的內部,你只是退出你的guard聲明。


如果您使用PromiseKit/Alamofire和呼叫then,你可能希望創建一個可以返回,如一個承諾:

func list() -> Promise<String> { 
    return Alamofire.request(endPoint) 
     .validate() 
     .responseJSON() 
     .then { value in 
      return Promise { fulfill, reject in 
       guard let dictionary = value as? [String: Any], let name = dictionary["name"] as? String else { 
        reject(ActivityError.malformed("not dictionary")) 
        return 
       } 

       fulfill(name) 
      } 
    } 
} 

或者如果太毛茸茸的,你可以拉出value的語法分析:

func list() -> Promise<String> { 
    return Alamofire.request(endPoint) 
     .validate() 
     .responseJSON() 
     .then { value in 
      self.parse(value) 
    } 
} 

func parse(_ value: Any) -> Promise<String> { 
    return Promise { fulfill, reject in 
     guard let dictionary = value as? [String: Any], let name = dictionary["name"] as? String else { 
      reject(ActivityError.malformed("not dictionary")) 
      return 
     } 

     fulfill(name) 
    } 
} 

但是,無論哪種方式,即使使用PromiseKit/Alamofire的時候,你還只是return 012內條款。

+0

這不行,我其實需要在那裏返回一個Promise。返回void不會生成。 – sssilver

+1

爲什麼「那不行」?去試試吧,它會 – redent84

+0

我試過了。注意到我正在使用PromiseKit/Alamofire,並且HTTP響應返回到promise(),它不能只返回一個Void。它需要返回一個Promise。 – sssilver