2017-04-03 52 views
0

我們有一個正在增長的應用程序,我們的客戶端腳本需要被重構爲更清潔,更精簡和更易於維護。我正試圖利用一個小模塊來利用承諾鏈接庫。如何轉換爲使用Promises和Q庫

正如你所看到的,我需要將一些返回值從初始函數傳回給promise鏈的其餘部分。 有人可以幫助我瞭解我需要做什麼才能讓第一個函數正確返回作爲承諾嗎?然後解釋鏈?

這裏是我的出發點:

var promise = new Q.Promise(generateMoveRequest) 
    .then(function (id) { 
     var woNum = 12345; 
     return layoutInit(woNum, id, true); 
    }).then(function (result) { 
     if (result) { 
      return moveRequestInit(result, true); 
     } else { 
      throw new Error('Template not loaded'); 
     } 
    }).catch(function (err) { 
     console.log(err); 
    }); 

生成移動請求:

generateMoveRequest: function() { 
     $.ajax({ 
      method: "GET", 
      url: window.contextPath + '/api/settings/getjson', 
      data: {name: "the_name"}, 
      success: function (data) { 
       if (data.length) { 
        var id = $.parseJSON(data).Parent;           
        return id; 
       } 
      }, 
      error: function (xhr, textStatus, errorThrown) { 
       console.log("xhr: ", xhr); 
       return null; 
      } 
     }); 
    } 

佈局初始化:

layoutInit: function (num, id, appendLayout) { 
    $.ajax({ 
      method: "GET", 
      url: window.contextPath + '/some/url', 
      data: {num: num, id: id}, 
      success: function (data) { 
       return layoutInit.callback(data, appendLayout); 
      }, 
      error: function (xhr, textStatus, errorThrown) { 
       console.log("xhr: ", xhr); 
      } 
     }); 
    }, 
    callback: function (data, appendLayout) { 
     if (data && data.toString().toLowerCase() !== "blank") { 
      if (appendLayout) { 
       $(data).insertBefore($("#detailsection")); 
      } else { 
       $("#detailsection").html(data); 
      }        
     } else { 
      $("#detailsection").html(''); 
     } 
    }, 

generateMoveRequest函數將執行,但鏈永遠不會繼續。沒有。然後()執行和layoutInit永遠不會被調用。

我正在使用Q庫,但一些例子似乎忽略瞭如何開始/創建承諾或將初始函數轉化爲Promise。

有人可以解釋我在這裏有什麼錯,或爲我提供一個乾淨的例子嗎?

+0

你的函數'generateMoveRequest'應該返回的東西:'$ .ajax'返回一個承諾(它有一個'then'方法),所以你可以返回。 – trincot

+0

@trincot我讓它返回一個值=> id – Encryption

+0

這是成功回調的返回值,而不是函數'generateMoveRequest'。 – trincot

回答

1

jQuery的落實承諾不符合A +標準,所以你與Q.更好

的承諾必須得到一個函數有兩個參數的 - resolvereject - 這也是函數(記住, Javascript是一種功能性語言)。必須在成功時調用resolve函數,並在出錯時調用reject。無論您傳遞給這些函數,都將在then()catch()回調中提供。

長話短說,重寫代碼是這樣的:

var generateMoveRequest = function (resolve, reject) { 
    $.ajax({ 
    method: "GET", 
    url: window.contextPath + '/api/settings/getjson', 
    data: {name: "the_name"}, 
    success: function (data) { 
     if (data.length) { 
     var id = $.parseJSON(data).Parent; 
     resolve(id); 
     } else { 
     reject({message: 'Data not received'}) 
     } 
    }, 
    error: function (xhr, textStatus, errorThrown) { 
     reject({message: errorThrown}) 
    } 
    }); 
} 

var promise = new Q.Promise(generateMoveRequest) 
    .then(function (id) { 
     var woNum = 12345; 
     return layoutInit(woNum, id, true); 
    }).then(function (result) { 
     if (result) { 
      return moveRequestInit(result, true); 
     } else { 
      throw new Error('Template not loaded'); 
     } 
    }).catch(function (error) { 
     console.log(error.message) 
    }); 

後來編輯 - 看到片段明白承諾是如何工作的:

// any number of params 
function willPerformAnAsyncOperationAndReturnAPromise(firstParam, secondParam, thirdParam) { 
    var promise = new Q.Promise(function (resolve, reject) { // always resolve & reject 
    // perform an async operation, like waiting one second 
    window.setTimeout(function() { 
     if (firstParam !== 0) { 
     // if the 1st param is not 0, it's a success 
     resolve ({ 
      first: firstParam, 
      second: secondParam, 
      third: thirdParam 
     }) 
     } else { 
     reject({message: 'The first param must not be null'}) 
     } 
    }, 1000) 
    }) 

    return promise 
} 

willPerformAnAsyncOperationAndReturnAPromise(1, 2, 3) 
    .then(function (data) { 
    console.log(data) 
    }) 
    .catch(function (error) { 
    console.log(error) 
    }) 

willPerformAnAsyncOperationAndReturnAPromise(0, 2, 3) 
    .then(function (data) { 
    console.log(data) 
    }) 
    .catch(function (error) { 
    console.log(error) 
    }) 
+0

謝謝。非常感激!我現在認識到,任何Promise函數都必須明確地解析和拒絕。現在更有意義。之後就像魅力一樣工作。 – Encryption

+0

它的工作原理,但它使用['承諾構造函數antipattern'](http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-doi-i-避免它),因爲'$ .ajax'已經是一個承諾。 – trincot

+1

請注意,從jQuery 3.0開始,jQuery對Promises的實現是[A +符合](https://promisesaplus.com/implementations#inside-frameworks)。 –

0

的一些問題:

  • 你函數generateMoveRequest應該返回一些東西:$.ajax返回一個承諾(它有一個then方法),所以你可以返回它;

  • 您不需要創建新的承諾,因爲generateMoveRequest返回一個。這樣你就避免了promise constructor anti-pattern

建議代碼:

generateMoveRequest: function() { 
    return $.ajax({ 
     method: "GET", 
     url: window.contextPath + '/api/settings/getjson', 
     data: {name: "the_name"}, 
    }).then(function (data) { 
     if (data.length) { 
      var id = $.parseJSON(data).Parent;           
      return id; 
     } 
    }).catch(function (xhr, textStatus, errorThrown) { 
     console.log("xhr: ", xhr); 
     return null; 
    }) 
} 

var promise = generateMoveRequest() 
    .then(function (id) { 
     var woNum = 12345; 
     return layoutInit(woNum, id, true); 
    }).then(function (result) { 
     if (result) { 
      return moveRequestInit(result, true); 
     } else { 
      throw new Error('Template not loaded'); 
     } 
    }).catch(function (err) { 
     console.log(err); 
    }); 
+0

downvoter能否發表評論,以便我知道我錯過了什麼? – trincot

相關問題