【问题标题】:Which way of resolving a value from a promise is correct?从 Promise 中解决值的哪种方法是正确的?
【发布时间】:2017-08-13 17:35:59
【问题描述】:

我对 JavaScript 中的所有这些异步内容仍然很陌生,并且在处理一些 Promise 时遇到了一些令人困惑的情况。这是我当前的代码:

exists(filename, targetDir){
    const filepath = path.join(targetDir || this.getTargetDir(), filename);
    // plug in any one method from below
}

当我查看其他人的代码时,我看到他们解析这样的值(插入上面的代码):

// method 1
return request(this.getUrl(filepath))
    .then(res => {
        return Promise.resolve(res.statusCode === 200);
    })
    .catch(() => {
        return Promise.resolve(false);
    });

// method 2
return request(this.getUrl(filepath))
    .then(res => {
        Promise.resolve(res.statusCode === 200);
    })
    .catch(() => {
        Promise.resolve(false);
    });

// method 3
return request(this.getUrl(filepath))
    .then(res => {
        return res.statusCode === 200;
    })
    .catch(() => {
        return false;
    });

// method 4
return new Promise((resolve, reject) => {
    request(this.getUrl(filepath))
        .then(res => {
            resolve(res.statusCode === 200);
        }
        .catch(() => {
            resolve(false);
        };
});

在这种情况下哪些是正确的?哪些是不正确的?这取决于场景吗?推荐其中哪一种?一个很好的解释将不胜感激,谢谢!

澄清: exists 是一个类方法,它返回一个解析为布尔值的 Promise,其中true 表示 URL 存在,false 表示它不存在.

澄清 #2: 如果发生错误,exists 应解析为 false

【问题讨论】:

  • @guest271314 基本上我试图找出从承诺中解析值的哪种方法是正确的。
  • 第一种和第三种方法都是正确的,做同样的事情
  • @guest271314,回调传递给then应该返回Promise,如果它返回的不是Promise,那么result就会被包装。因此,在第一种方法中,只需手动执行此操作
  • @guest271314,是的,如果这已经不是一个承诺,那么,如果你返回 Promise,就像在第一个方法中一样,这个值不会被包装在另一个承诺中
  • @guest271314 是的,exists 应该返回一个解析为 truefalse 的 Promise。

标签: javascript ecmascript-6 promise


【解决方案1】:
  • 方法 1 正确但不必要的复杂。

  • 方法 2 完全错误。
    您创建了新的 Promise,但它们没有填充到任何地方,因此它们在函数结束时被释放。
    相当于:

    return request(this.getUrl(filepath)).catch(err => undefined);
    
  • 方法 3 是最好的方法。

  • 方法 4 也可以解析为 corect 值,但它是一种反模式。
    What is the explicit promise construction antipattern and how do I avoid it?

【讨论】:

  • 第四种方法呢?
  • @Grundy 更新了答案(总结:避免)
  • @guest271314 - 方法 1 有效。可以从 .then() 处理程序返回已解决的承诺。所以,大概这就是他所说的“正确”的意思。这不是最优的,因为根本没有理由返回一个承诺,一个人可以像 Thomas 推荐的方法 3 一样从 .then() 处理程序返回一个普通值。
  • @jfriend00 .then() 返回一个Promise。为什么返回Promise.resolve()
  • @guest271314 - 是的,它们是等价的,任何一个都是允许的。显然,return false 更简单。
【解决方案2】:

方法3最好。

下一个.then() 接收当前.then() 返回的内容。如果这个返回值恰好是一个promise,那么下一个.then()会在promise解决后执行。

使用方法3,您将能够将其他.then()s 附加到当前链:

exists('test.txt', '/')
  .then(doesExist => console.log(doesExist ? 'The file exists.' : 'The file doesn\'t exist.'));

方法 1 和方法 4 也可以做到这一点,但方法 1 不必要地将值包装在将立即解析的承诺中。

方法 4 不必要地将整个请求包装在一个 Promise 中。这称为explicit-construction anti-pattern

方法 2 不允许 Promise 链接。您不能使用包裹在 Promise.resolve 中的值,因为 .then().catch() 都隐式返回 undefined

【讨论】:

  • 请注意,方法 3 中 .catch() 内的 return false 将导致链接 .then() 处的已解析 Promise 值 - 将无法到达链接 .catch()
  • 我猜这是故意的。如果文件存在,exists 应该返回一个包装 true 的承诺,如果文件不存在或出现错误,则包装 false.catch()s after exists 应该只处理出现在.then()s after 存在的错误。
  • "如果文件不存在则包装 false" 如何到达.catch()
  • 您能否澄清一下特定的.catch() 在哪里?请参阅this gist。
  • 在问题 .catch(() => { return false; }); 的代码中的方法 3 将导致在链式 .then() 处解析 Promise
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 2015-04-24
  • 2021-12-30
  • 2022-11-17
  • 1970-01-01
  • 2016-11-25
  • 2013-03-15
相关资源
最近更新 更多