Javascript承诺中的错误处理

mib*_*tec 5 javascript ajax jquery promise

我有一些Javascript代码执行一些异步的东西与一些同步后处理,然后再次异步的东西(XHR - >解析XHR - >新的XHR基于第一个).我没有完成错误处理:

/* API */
function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        return data.id
    }, handleError)
}

function handleError(errorObj) {
    if (errorObj.status) {
        return errorObj.status
    } else {
        return errorObj
    }
}

function myApiCall() {
    return getFile(1)
        .then(getFile, handleError)
        .then(getFile, handleError)
        .then(getFile, handleError)
        .then(getFile, handleError);
}


/* caller */

function failFunction(status) {
    console.log("fail: ")
    console.log(status)
}

myApiCall().then(function(id) {
        console.log(id)
    }, failFunction)
Run Code Online (Sandbox Code Playgroud)

1.json 看起来像这样

{
    "id": "2"
}
Run Code Online (Sandbox Code Playgroud)

只是引用下一个文件,其他文件是等效的.

直到这里一切都很好(即使我不确定这是否是做错误处理的最佳方式).如果存在所有文件,则调用调用者的成功函数,否则调用错误函数.

但是当我的同步代码中出现一些错误时,everthing会中断

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        throw new Error(42) //       <---------
    }, handleError)
}
Run Code Online (Sandbox Code Playgroud)

现在我得到一个控制台输出

Error: 42
Run Code Online (Sandbox Code Playgroud)

没有进一步处理,来电者不会被告知.

我尝试过类似的东西

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        throw new Error(42)
    }, handleError)
    .catch(handleError)
}
Run Code Online (Sandbox Code Playgroud)

但这并没有让事情变得更好.最重要的是,我得到了一个TypeError: $.ajax(...).then(...).catch is not a function

在这种情况下,错误处理如何解决?

Jar*_*a X 10

因为您在每个阶段处理错误而不是传播它们,所以您最终会遇到问题

编辑:

上面的陈述是错误的,我没有意识到当我编写它时,jquery承诺是多么破碎 - 看到第一个代码块(Promise/A +)和第二个代码块之间的区别(jQuery承诺用手指交叉在后面)

相反,你可以做类似的事情:

function getFile(name) {
  // wrap jquery "promise" in real Promise
  // you'll need a Promise polyfill for Internet Explorer to use this method
  return new Promise(function(resolve, reject) {
    $.ajax({
      url: name + ".json?" + Math.random()
    }).then(function(data) {
      resolve(data.id);
    }, function(err) {
      reject(err);
    });
  });
}

function handleError(errorObj) {
  //console.log(errorObj)
  if (errorObj.status) {
    throw errorObj.status;
  } else {
    throw errorObj;
  }
}

function myApiCall() {
  return getFile(1)
  .then(getFile)
  .then(getFile)
  .then(getFile)
  .then(getFile)
  .catch(handleError);
}

function failFunction(status) {
  console.log("fail: ")
  console.log(status)
}

myApiCall().then(function(id) {
  console.log(id);
})
.catch(failFunction);
Run Code Online (Sandbox Code Playgroud)

当使用jQuery时,你的承诺就像是你用手指交叉背后的承诺

function getFile(name) {
    return $.ajax({
        url: name + ".json"
    }).then(function(data) {
        return data.id;
    });
}
function handleError(errorObj) {
    if (errorObj.status) {
        return errorObj.status; // return in jquery!
    } else {
        return errorObj;
    }
}
function myApiCall() {
    return getFile(1)
        .then(getFile)
        .then(getFile)
        .then(getFile)
        .then(getFile)
        .fail(handleError); // like jquery promises in general, use fail instead of the compliant catch
}
/* caller */
function failFunction(status) {
    console.log("fail: ");
    console.log(status);
}
myApiCall().then(function(id) {
    console.log(id);
})
.fail(failFunction);
Run Code Online (Sandbox Code Playgroud)

  • 请避免使用promise构造函数反模式,只需使用`Promise.resolve($ .ajax(...))`.jQuery至少在A +术语中是可以的. (2认同)