使用普通的JS承诺编写jQuery AJAX请求

时间:2016-08-26 18:26:32

标签: javascript jquery ajax promise

我目前正在将我的网页移到SPA(单页面应用程序),这样做我现在只使用一个html页面,使用JS填充(正常的SPA应该这样做)。因此,这意味着(为了方便起见)我将我的JS文件减少到一个(也许是一个好主意,也许是一个糟糕的 - 我们会看到,但这不是重点)。我决定制作一个黑盒子" AJAX请求处理程序,以便最小化代码。这是我遇到一个我没想到的问题。代码是(示例click用于我的登录屏幕):

function ajaxCall(type, url, data, dataType) {
  $.ajax({
    type: type,
    url: url,
    data: data,
    dataType: dataType,
  })
  .done(function(xhr) {
    return xhr;
  })
  .fail(function(xhr, status, errorThrown) {
    console.log('AJAX call error: ' + errorThrown);
    console.dir(xhr);
  })
  .always(function(xhr, status) {
    console.log('AJAX call status: ' + status);
  });
}

var res;
//this is inside $(document).ready - I just skipped some lines
$(document).on('click', '#submit', function(e) {
  res = ajaxCall('POST', '/Login', { 'username': $('#username').val(), 'password': $('#password').val() }, 'json');

  console.log('res =', res); // this is where the problem was discovered
});

(有些人已经在呻吟)当然,当我测试这个时,我在控制台中得到的是res = undefined

我花了几个小时研究这个问题,并弄清楚它发生的原因。这些是我在尝试解决此问题时所研究的一些页面:1 2 3

切入追逐:问题是我没有使用Promise。我明白了。我可以解决这个问题。我似乎无法修复的是使用带有jQuery AJAX请求的普通JS Promise

我已经走到了这一步:

function ajaxCall(type, url, data, dataType) {
  return Promise.resolve($.ajax({
    type: type,
    url: url,
    data: data,
    dataType: dataType,
  }));
}

但我无法弄清楚如何合并promise的其他功能/功能,其中包括:.then() and .reject()据我了解,上述承诺将会自动解决,但如果需要拒绝怎么办?也许我还在想jQuery' .done(), .fail() and .always()

  

但是对于我的生活,尽管我做了所有谷歌搜索,我找不到如何将纯JS Promise的所有函数与jQuery AJAX请求完全合并。

因此,我要求stackoverflow社区深入了解这个问题。

谢谢。

1 个答案:

答案 0 :(得分:2)

所以Promise在这里并不是你的救世主。您遇到的问题是,在使用console.log('res =', res);.done()方法完成AJAX请求后,您需要调用.fail()

function ajaxCall(type, url, data, dataType) {
  return $.ajax({
    type: type,
    url: url,
    data: data,
    dataType: dataType,
  });
}

//this is inside $(document).ready - I just skipped some lines
$(document).on('click', '#submit', function(e) {
  var res = ajaxCall('POST', '/Login', { 'username': $('#username').val(), 'password': $('#password').val() }, 'json');
  res.done(function (data) {
    console.log('res =', data);
  });
});

如果您真的想使用真实的Promise,可以执行类似

的操作
function ajaxCall(type, url, data, dataType) {
  return new Promise(function (resolve, reject) {
    $.ajax({
      type: type,
      url: url,
      data: data,
      dataType: dataType,
    }).done(function (data) {
      resolve(data);
    }).fail(function (jqXHR, textStatus, errorThrown) {
      reject(errorThrown);
    });
  });
}

//this is inside $(document).ready - I just skipped some lines
$(document).on('click', '#submit', function(e) {
  var res = ajaxCall('POST', '/Login', { 'username': $('#username').val(), 'password': $('#password').val() }, 'json');
  res.then(function (data) {
    console.log('res = ', data);
  }).catch(function (err) {
    console.error(err);
  });
});