JavaScript中的Promises

2022-12-18 0 473

责任编辑并行生前提前布局网络平台的创作者译者:

https://juejin.cn/post/6844903834402160648

你是不是在JavaScript中碰到过promises并想晓得它是甚么?它为甚么会被称作promises呢?它与否和你以任何人形式对另两个人作出的允诺相关呢?

除此之外,你为甚么要采用promises呢?与现代的JavaScript操作方式反弹(callbacks)较之,它有甚么益处呢?

在责任编辑中,你将自学相关JavaScript中promises的大部份文本。你将晓得它是甚么,是不是去采用它,和为甚么它比反弹更畅销。

因此,promise是甚么?

promise是两个今后会codice的第一类。虽然此种今后的小东西,Promises适于触发器JavaScript操作方式。

假如你不晓得触发器JavaScript意味著甚么,你可能还不适宜读这首诗。我提议你返回有关callbacks这首诗介绍后再回去。

透过等效会更快地导出JavaScript promise的基本概念,因此我们来这种做(等效),使其基本概念更为明晰。

想像呵呵,你预备下周一为你的孙女举行生日会。当你谈及舞会时,你的好友,Jeff,提出他能提供更多协助。你极高心,让他买两个科布伦茨(艺术风格的)花篮。Jeff说能。

在这儿,Jeff说你他会给你买两个科布伦茨花篮。这是签订合同好的。在JavaScript中,promise的组织工作形式和现实生活中的允诺那样。能采用下列形式撰写JavaScript版的情景:

// jeffBuysCake is a promise const promise = jeffBuysCake(black forest) 拷贝标识符

你将自学怎样构筑jeffBuysCake。那时,把它当做两个promise。

那时,Jeff仍未采取措施。在JavaScript中,我们说允诺(promise)正在等待中(pending)。假如你console.log两个promise第一类,就能验证这点。

JavaScript中的Promises

打印jeffBuysCake表明允诺正在等待中。

当我们稍后一起构筑jeffBuysCake时,你将能够自己证明此console.log语句。

在与Jeff交谈之后,你开始计划下一步。你意识到假如Jeff信守诺言,并在聚会时买来两个科布伦茨蛋糕,你就能按照计划继续舞会了。

假如Jeff确实买来了蛋糕,在JavaScript中,我们说这个promise是实现(resolved)了。当两个允诺得到实现时,你会在.then调用中做下一件事情:

jeffBuysCake(black forest) .then(partyAsPlanned)// Woohoo! 拷贝标识符

假如Jeff没给你买来蛋糕,你必须自己去面包店买了。(该死的,Jeff!)。假如发生此种情况,我们会说允诺被拒绝(rejected)了。

当允诺被拒绝了,你能在.catch调用中执行应急计划。

jeffBuysCake(black forest) .then(partyAsPlanned) .catch(buyCakeYourself) // Grumble Grumble… #*$% 拷贝标识符

我的好友,这就是对Promise的剖析了。

某些操作方式。当promise拒绝时,我们处理错误:

getSomethingWithPromise() .then(data => {/* do something with data */}) .catch(err => {/* handle the error */}) 拷贝标识符

那时,你晓得两个promise怎样运作了。让我们进一步深入研究怎样构筑两个promise。

构筑两个promise

你可以采用new Promise来创建两个promise。这个Promise构造函数是两个包含两个参数 — resolve和reject 的函数。

const promise = new Promise((resolve, reject) => { /* Do something here */ }) 拷贝标识符

假如resolve被调用,promise成功并继续进入then链式(操作方式)。你传递给resolve的参数将是接下来then调用中的参数:

const promise = new Promise((resolve, reject) => { // Note: only 1 param allowed return resolve(27) }) // Parameter passed resolve would be the arguments passed into then.promise.then(number => console.log(number)) // 27 拷贝标识符

假如reject被调用,promise失败并继续进入catch链式(操作方式)。同样地,你传递给reject的参数将是catch调用中的参数:

const promise = new Promise((resolve, reject) => { // Note: only 1 param allowed returnreject() })// Parameter passed into reject would be the arguments passed into catch. promise.catch(err => console.log(err)) // 拷贝标识符

你能看出resolve和reject都是反弹函数吗?

让我们练习呵呵,尝试构筑jeffBuysCake promise。

首先,你晓得Jeff说他会买两个蛋糕。那就是两个允诺。因此,我们从空promise入手:

const jeffBuysCake = cakeType => { return new Promise((resolve, reject) => { // Do something here }) } 拷贝标识符

接下来,Jeff说他将在一周内购买蛋糕。让我们采用setTimeout函数模拟这个等待七天的时间。我们将等待一秒,而不是七天:

constjeffBuysCake =cakeType => { return new Promise((resolve, reject) => { setTimeout(()=> { // Checks if Jeff buys a black forest cake }, 1000) }) } 拷贝标识符

假如Jeff在一秒之后买了个科布伦茨蛋糕,我们就会返回promise,然后将科布伦茨蛋糕传递给then。

假如Jeff买了另一种类型的蛋糕,我们拒接这个promise,并且说no cake,这会导致promise进入catch调用。

const jeffBuysCake = cakeType => { return new Promise((resolve, reject) => { setTimeout(()=> { if (cakeType – = black forest) { resolve(black forest cake!) } else { reject(No cake ) } }, 1000) }) } 拷贝标识符

让我们来测试下这个promise。当你在下面的console.log记录时,你会看到promise正在pedding(等待)。(假如你立即检查控制台,状态将只是暂时挂起状态。假如你需要更多时间检查控制台,请随时将超时时间延长至10秒)。

const promise = jeffBuysCake(black forest) console.log(promise) 拷贝标识符
JavaScript中的Promises

打印jeffBuysCake表明允诺正在等待中。

如果你在promise链式中添加then和catch,你会看到black forest cake!或no cake 信息,这取决于你传入jeffBuysCake的蛋糕类型。

constpromise = jeffBuysCake(black forest) .then(cake => console.log(cake)) .catch(nocake => console.log(nocake)) 拷贝标识符
JavaScript中的Promises

打印出来是“科布伦茨蛋糕”还是“没有蛋糕”的信息,取决于你传入jeffBuysCake的(参数)。

创建两个promise不是很难,是吧?

既然你晓得甚么是promise,怎样制作两个promise和怎样采用promise。那么,我们来回答下两个问题 — 在触发器JavaScript中为甚么要采用promise而不是反弹呢?

Promises vs Callbacks

开发人员更喜欢promises而不是callbacks有三个原因:

Promise减少了嵌套标识符的数量Promise允许你轻松地可视化执行流程Promise让你能在链式的末尾去处理大部份错误

为了看到这三个益处,让我们撰写一些JavaScript标识符,它透过callbacks和promises来做一些触发器事情。

对于这个过程,假设你正在运营两个在线商店。你需要在客户购买小东西时向他收费,然后将他们的信息输入到你的数据库中。最后,你将向他们发送电子邮件:

向客户收费将客户信息输入到数据库发送电子邮件给客户

假如你采用Express或Node,则初始化标识符可能如下所示。假如你不晓得任何人Node或Express(的知识点),请不要担心。它不是责任编辑的主要部分。跟着下面来走:

// A little bit of NodeJS here. This is how youll get data from the frontend through your API. app.post(/buy-thing, (req, res) => {const customer = req.body // Charge customer here }) 拷贝标识符

让我们先介绍呵呵基于callback的标识符。在这儿,你想要向客户收费。如果收费成功,则将其信息添加到数据库中。假如收费失败,则会抛出错误,因此你的服务器能处理错误。

标识符如下所示:

// Callback based code app.post(/buy-thing, (req, res) => { const customer = req.body // First operation: charge the customer chargeCustomer(customer, (err, charge) => { if (err) throw err // Add to database here }) }) 拷贝标识符

那时,让我们切换到基于promise的标识符。同样地,你向客户收费。假如收费成功,则透过调用then将其信息添加到数据库中。假如收费失败,你将在catch调用中自动处理:

// Promised based code app.post(/buy-thing, (req, res) => { const customer = req.body // First operation: charge the customerchargeCustomer(customer) .then(/* Add to database */) .catch(err => console.log(err)) }) 拷贝标识符

继续,你能在收费成功后将你的客户信息添加到数据库中。假如数据库操作方式成功,则会向客户发送电子邮件。否则,你会抛出两个错误。

考虑到这些步骤,基于callback的标识符如下:

// Callback based code app.post(/buy-thing, (req, res) => { const customer = req.body chargeCustomer(customer, (err, charge) => { if (err) throw err // Second operation: Add to database addToDatabase(customer, (err, document) => { if (err) throw err // Send email here }) }) }) 拷贝标识符

对于基于promise的标识符,假如数据库操作方式成功,则在下两个then调用时发送电子邮件。假如数据库操作方式失败,则会在最终的catch语句中自动处理错误:

// Promised based code app.post(/buy-thing, (req, res) => { constcustomer = req.body chargeCustomer(customer)// Second operation: Add to database .then(_ =>addToDatabase(customer)) .then(/* Send email */) .catch(err => console.log(err)) }) 拷贝标识符

继续最后一步,在数据库操作方式成功时向客户发送电子邮件。假如成功发送此电子邮件,则会有成功消息通知到你的前端。否则,你抛出两个错误:

下列是基于callback的标识符:

app.post(/buy-thing, (req, res) =>{ const customer = req.body chargeCustomer(customer,(err, charge) => { if (err) throwerr addToDatabase(customer,(err, document) => { if (err) throw err sendEmail(customer, (err, result) => { if (err) throw err // Tells frontend success message. res.send(success!) }) }) }) }) 拷贝标识符

然后,下列基于promise的标识符:

app.post(/buy-thing, (req, res) => { constcustomer = req.body chargeCustomer(customer) .then(_ => addToDatabase(customer)) .then(_ => sendEmail(customer) ) .then(result =>res.send(success!))) .catch(err => console.log(err)) }) 拷贝标识符

看看为甚么采用promises而不是callbacks撰写触发器标识符要容易得多?你从反弹地狱(callback hell)呵呵子切换到了链式乐土上。

一次触发多个promises

promises比callbacks的另两个益处是,假如操作方式不依赖于彼此,则能同时触发两个(或多个)promises,但是执行第三个操作方式需要两个结果。

为此,你采用Promise.all方法,然后传入一组你想要等待的promises。then的参数将会是两个数组,其包含你promises返回的结果。

const friesPromise = getFries() const burgerPromise = getBurger() const drinksPromise = getDrinks() consteatMeal =Promise.all([ friesPromise, burgerPromise, drinksPromise ]) .then([fries, burger, drinks] => {console.log(`Chomp. Awesome ${burger}! `) console.log(`Chomp. Delicious ${fries}! `) console.log(`Slurp. Ugh, shitty drink ${drink} `) }) 拷贝标识符

备注:还有两个名为Promise.race的方法,但我还没找到合适的用例。你能点击这儿去查看。

最后,我们来谈谈浏览器支持情况!假如你不能在生产环境中采用它,那为甚么要自学promises呢。是吧?

浏览器支持Promise

令人兴奋的消息是:大部份主流浏览器都支持promises!

假如你需要支持IE 11及其下列版,你能采用Taylor Hakes制作的Promise Polyfill。它支持IE8的promises。

结语

你在责任编辑中学到了所相有关promises的知识。简而言之,promises棒极了。它能协助你撰写触发器标识符,而无需进入反弹地狱。

尽管你可能希望无论甚么时候都采用promises,但有些情况callbacks也是有意义的。不要忘记了callbacks啊。

感谢阅读。这首诗与否协助到你?假如有,我希望你考虑分享它。你可能会协助到其他人。非常感谢!

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务