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

Why do we need Promise in JS

本文关键字:Promise 我们 JS 为什么      更新时间:2023-09-26

我刚刚在两个MDN上看到了关于Promise的消息。我能理解语法,但不确定我们为什么需要它。

是否存在只能使用Promise来完成的特定情况?或者它只是一种编写更简洁代码的方法?

承诺使我们能够编写更简洁的代码,同时减少(或完全消除)回调。

此外,回调是ES2017中一些新语法特性的骨干,例如async functions,它允许更干净的方式编写代码。

promise所做的第三件事在您第一次学习语法时并不明显——自动错误处理。承诺允许错误被传递到链的下游,并在一个公共的地方进行处理,而不需要添加手动错误处理层。

目前,没有JavaScript承诺就做不到的事情,因为最初的承诺实现也是JavaScript代码。使用承诺的一个理由是摆脱所谓的"回调地狱",它看起来像这样:

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

这可以很容易地通过简单地给函数命名来解决:

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

因此&;callback hell&;是一种误解,真正的问题应该被称为"匿名函数地狱"。顺便说一下,仅仅使用承诺也不会阻止这种情况,就像下面的例子:

samplePromise().then(function () {
    samplePromise().then(function () {
        samplePromise().then( function () {
            // do something
        });
    });
});

看到一个模式了吗?匿名函数又一次成为了深度嵌套的罪魁祸首。

话虽这么说,有一个用例可能会从承诺中受益,那就是当来自多个异步调用的异常可以被同一个catch块捕获时:

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

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

从MDN文档的第一行开始:

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

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

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

它说:

在第一轮中,承诺可以缓解"厄运金字塔":代码向右移动的速度比向前移动的速度快。

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的处理程序确实在所有其他代码异步运行之后被调用。

第二,只有当承诺被履行时,才调用履行处理程序,并使用它被解析的值(在我们的例子中,是掷骰子的结果)。对于拒绝处理程序也是如此。

感谢Mozilla和Toptotal