如何转换为使用Promises和Q库

时间:2017-04-03 20:05:08

标签: javascript jquery promise q

我们有一个正在发展的应用程序,我们的客户端脚本需要重构为更清洁,更精简,更易于维护。我正在尝试将一个小模块用于使用 Q 库进行保证链接。

正如您所看到的,我需要将一些返回值从初始函数传递回promise链的其余部分。 有人可以帮我理解我需要做些什么才能使第一个函数作为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 函数将执行,但链永远不会再继续。没有.then()执行和 layoutInit 永远不会被调用。

我正在使用Q库,但有些示例似乎忽略了如何启动/创建承诺或将初始函数转换为Promise。

有人可以解释我在这里遇到的错误或给我一个干净的例子吗?

2 个答案:

答案 0 :(得分:1)

承诺的jQuery实现不遵循A +标准,所以你最好用Q.

承诺必须接收带有2个参数的函数 - 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)
    });

稍后编辑 - 请参阅片段以了解Promise的工作原理:

// 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)
  })

答案 1 :(得分:0)

一些问题:

  • 您的函数var myJSON = Json.stringify(JiraJson); 应该返回一些内容:string jsonString = @"{""fields"":{""customfield_12302"":{""name"":""xyz""}}}"; 返回一个承诺(它有一个generateMoveRequest方法),所以你可以返回它;

  • 您无需创建新承诺,因为$.ajax会返回一个承诺。这样就可以避免使用promise constructor anti-pattern

建议代码:

then