为什么我们需要在JS中使用Promise?

14

我刚刚在MDN上读到了 Promise,我理解了语法,但不确定为什么需要它。

有没有一些特定的情况只能使用 Promise 来完成?还是说它只是一种更简洁的代码编写方式?


1
我们需要它,因为在函数式JS中,它是必不可少的。 - Redu
3
使用Promise无法完成的事情在“标准”JavaScript中也可以完成。它是异步操作的一个非常强大的抽象,可以使代码更加简洁。但是,它完全是可选的。 - m90
此外,如果只有一层嵌套,我觉得使用回调函数会更容易。 - D-Marc
5个回答

9
承诺使我们能够编写更干净的代码,从而减少(或完全消除)回调地狱。
此外,回调是ES2017中一些新语法功能的支柱,例如“async函数”,这允许更干净的编写方式。
当您第一次学习语法时,承诺所做的第三件事并不立即显现-自动错误处理。 承诺允许将错误传递到链条下面,并在一个常见位置处理错误,而无需添加多层手动错误处理。

仅凭承诺无法解决“回调地狱”。它们也不是解决这类问题的唯一方法。 - Diogo Eichert

4

目前来说,使用JavaScript promises无法完成任何原本不能通过其它方式实现的功能,因为Promise最初的实现也是由JavaScript代码编写的。使用Promise的优点之一在于摆脱了所谓的“回调地狱”,它看起来像这样:

setTimeout(function () {
    setTimeout(function() {
        setTimeout(function() {
            // do something
        }); 
    }); 
});

通过为函数命名,可以轻松解决这个问题:

setTimeout(doSomething);

function doSomething() {
    setTimeout(doSomethingElse);
}

function doSomethingElse() {
    // do something
}

所以,“回调地狱”是一个误解,真正的问题应该被称为“匿名函数地狱”。顺便说一句,仅仅使用 Promise 也无法解决这个问题,就像以下样例一样:
samplePromise().then(function () {
    samplePromise().then(function () {
        samplePromise().then( function () {
            // do something
        });
    });
});

看到规律了吗?我们再次发现匿名函数是深层嵌套的罪魁祸首。

话虽如此,有一种情况可能可以从Promise中获益,那就是当来自多个异步调用的异常可以被同一个catch块捕获时:

new Promise(function (resolve, reject) {
    resolve("Blah");
}).then(function () {
    // do something
}).then(function () {
    // do something
}).catch(function (reason) {
    // error handling
});

1

Promise对象用于执行异步函数。

从MDN文档的第一行开始:

Promise对象用于异步计算。Promise表示尚未完成但预计将来会完成的单个异步操作。


问题在于MDN和其他地方的示例似乎不需要像那样编写。如果只是为了编写更清晰的代码,我可以理解。只是不确定是否有一些有用的东西隐藏在背后。 - Hp93

0

这只是为了编写更清晰的代码。看看这个例子:

https://www.npmjs.com/package/q

它说:
在第一次传递中,Promise 可以缓解“金字塔之谷”问题:即代码向右移动的速度比向前移动的速度更快的情况。

-1
Promise对象用于异步计算。Promise表示一个尚未完成但预期在未来完成的单个异步操作。
这里有一个例子。您可以在此运行它 http://jsbin.com/yumapi/5/edit?html,js,output
function dieToss() {
  return Math.floor(Math.random() * 6) + 1;
}

console.log('1');
var promise = new RSVP.Promise(function(fulfill, reject) {
  var n = dieToss();
  if (n === 6) {
    fulfill(n);
  } else {
    reject(n);
  }
  console.log('2');
});

promise.then(function(toss) {
  console.log('Yay, threw a ' + toss + '.');  
}, function(toss) {
  console.log('Oh, noes, threw a ' + toss + '.');  
});

console.log('3');

这个例子说明了两件事:

首先,我们附加到 Promise 的处理程序确实在所有其他代码异步运行后被调用。

其次,只有当 Promise 被履行时,才会调用履行处理程序,并使用它解决的值(在我们的情况下,是掷骰子的结果)。拒绝处理程序也是如此。

感谢 Mozilla 和 Toptotal


1
嗨,我理解语法的工作原理。只是这个例子并不是说明使用该工具的好案例。就像在你的例子中,我们可以用两个 console.log 行替换 fulfill() 和 _reject()_,并实现相同的结果。 - Hp93
2
不需要它。这只是为了像这样的情况和异步请求而创建的东西。如果你能理解其他人使用promise时的代码,就可以继续使用你当前的方法,没有问题。 - Muntasir Alam
请告诉我是否有帮助! - Muntasir Alam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接