首页 > 解决方案 > 为什么 Promise 链在这个例子中工作,没有抛出错误

问题描述

所以在第一个例子中,链一直执行到最后一个console.log,没有错误,但在第二个例子中,类似的,它确实出错了。为什么会发生这种情况,我能否以某种方式使第一个示例也引发错误?

我只知道它与向对象添加函数有关,因为如果test未定义,则链会中断,但我无法理解如何访问对象中不存在的键不会导致错误。

编辑:我刚刚意识到我的脑残。自然地访问test.something返回undefined而不是错误。

// EXAMPLE 1: Weird

var test = {};

test.f1 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(1)
    });
}

test.f2 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(2)
    });
}

test.f3 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(3)
    });
}

test.f4 = function(result) {
    console.log("result", result);
}

test.f1(1)
.then(test.f2)
.then(test.f3)
.then(test.shouldCauseError)
.then(test.f4)
// EXAMPLE 2: As expected

new Promise(function(resolve, reject) {
    resolve(1);
})
.then(function(result) {
    return new Promise(function(resolve, reject) {
        resolve(2)
    });
})
.then(function(result) {
    return new Promise(function(resolve, reject) {
        resolve(3)
    });
})
.then(shouldCauseError)
.then(function(result) {
    console.log("result:", result);
});

标签: javascript

解决方案


.then最多接受两个参数。第一个参数,如果存在,则在上层 Promise 已解决时运行。第二个参数,如果存在,则在上层 Promise 被拒绝时运行。

undefined允许作为第一个参数(或作为两个参数)传递-.then因为不存在任何参数,所以上层 Promise 将通过未.then更改的传递。

(也,.then(undefined, fn)等价于.catch(fn)

所以,你的

.then(test.shouldCauseError)

传递undefined.then,这意味着上面的 Promise.then 没有修改(并且没有抛出)传递 - 它进入.then链中的下一个,就好像.then(test.shouldCauseError)不在那里一样。

由于传递undefined.then非常好,您需要一些其他方法来创建错误 - 可能将您传递给.thens 的所有内容包装在一个函数中,该函数检查传递的表达式是否实际上是一个函数,如果不是,则返回一个抛出的函数:

.then(validate(test.shouldCauseError))

// EXAMPLE 1: Weird

var test = {};

test.f1 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(1)
    });
}

test.f2 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(2)
    });
}

test.f3 = function(result) {
    return new Promise(function(resolve, reject) {
        console.log("result", result);
        resolve(3)
    });
}

test.f4 = function(result) {
    console.log("result", result);
}

const validate = arg => {
  if (typeof arg !== 'function') {
    return () => {
      throw new Error();
    }
  }
  return arg;
};

test.f1(1)
  .then(validate(test.f2))
  .then(validate(test.f3))
  .then(validate(test.shouldCauseError))
  .then(validate(test.f4))
  .catch((err) => {
    console.log('Error caught');
  });

您还可以创建test一个代理,在访问目标对象上不存在的属性时返回一个抛出函数。

但这些都是奇怪的解决方案,因为正在解决的“问题”在 JS 中不被视为问题。如果你想避免这类错误,我更喜欢使用 Typescript 之类的东西来确保我传递的内容是正确的类型,而不是undefined.


推荐阅读