通过JavaScript的流行和最近的改进,JavaScript越来越成为Web程序员的最佳朋友。 和所有最好的朋友一样,JavaScript恪守诺言。
现在听起来有些奇怪,但这是事实。 当前大多数浏览器都支持Promise对象 。 一个promise就像一个函数一样,它代表了一段代码或您希望在将来某个时刻执行的任务。
这就是诺言的样子。
var myPromise = new Promise(function (resolve, reject) {
// Task to carry out goes here.
});
您可以在此处看到,当我们创建一个Promise时,我们给它一个参数,该参数是一个函数,其中包含我们希望在将来某个时刻执行的代码。 您可能还已经注意到传递给promise, resolve
和reject
的函数中的两个参数。 这些也是功能,是我们告诉Promise是否已完成承诺的方法。 这是您将如何使用它们:
var myPromise = new Promise(function (resolve, reject) {
if (true) {
resolve('Hello Tuts+ fans!');
} else {
reject('Aww, didn\'t work.');
}
});
由于if
语句将始终为真,因此该承诺显然总是会得到解决。 这只是出于学习目的,我们将在以后做一些更现实的事情,但是请想象一下,用一小段不确定100%确定会起作用的代码替换true
。
现在我们已经创建了一个承诺,我们如何使用它? 好吧,我们需要告诉它那些resolve
和reject
函数是什么。 我们通过使用promise的then
方法来做到这一点。
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
}, function (result) {
// Reject callback.
console.error(result);
});
因为我们的if语句始终通过其true
检查,所以上面的代码将始终记录“ Hello Tuts +粉丝!”。 到控制台。 它还将立即执行。 这是因为Promise构造函数中的代码是同步的,这意味着它不等待任何操作执行。 它具有继续需要的所有信息,并会尽快这样做。
但是,诺言真正发挥作用的地方是异步任务,即您不知道何时确切实现诺言的任务。 异步任务的真实示例是通过AJAX获取资源,例如JSON文件。 我们不知道服务器将花费多长时间来响应,甚至可能会失败。 让我们在我们的Promise代码中添加一些AJAX。
var myPromise = new Promise(function (resolve, reject) {
// Standard AJAX request setup and load.
var request = new XMLHttpRequest();
// Request a user's comment from our fake blog.
request.open('GET', 'http://jsonplaceholder.typicode.com/posts/1');
// Set function to call when resource is loaded.
request.onload = function () {
if (request.status === 200) {
resolve(request.response);
} else {
reject('Page loaded, but status not OK.');
}
};
// Set function to call when loading fails.
request.onerror = function () {
reject('Aww, didn\'t work at all.');
}
request.send();
});
这里的代码只是用于执行AJAX请求的标准JavaScript。 我们请求一个资源(在本例中为指定URL的JSON文件),然后等待它响应。 我们永远不会确切知道何时。 而且我们显然不想停止执行out脚本来等待它,那么我们该怎么办?
好吧,幸运的是,我们已经将此代码放入了promise中。 通过将其放在此处,我们基本上是在说:“嘿,一段代码,我现在必须走了,但是稍后我会给您打电话,告诉您何时执行。答应您这样做并告诉我完成后?” 代码会说:“是的,当然。我保证。”
在上面的代码段中要注意的重要事情是resolve
和reject
函数的调用。 请记住,这是我们兑现我们的承诺:代码已成功执行或未成功执行的方式。 否则,我们永远不会知道。
使用基本示例中的相同代码,我们可以看到promise中的AJAX请求现在将如何工作。
// Tell our promise to execute its code
// and tell us when it's done.
myPromise.then(function (result) {
// Prints received JSON to the console.
console.log(result);
}, function (result) {
// Prints "Aww didn't work" or
// "Page loaded, but status not OK."
console.error(result);
});
我知道我们可以相信您, myPromise
。
连锁承诺
现在,您可能会在这一点上考虑到promises只是具有更好语法的精美回调函数。 在一定程度上是正确的,但继续我们的AJAX示例,您需要再进行几个请求,每个请求都基于最后一个的结果。 或者,如果您需要先处理JSON,该怎么办?
使用回调来完成此操作将导致大量的函数嵌套,每个函数变得越来越难以跟踪。 幸运的是,在承诺的世界中,我们可以像这样将这些功能链接在一起。 这是一个示例,一旦我们在假博客上收到用户评论的JSON,然后在进行其他操作之前要确保其全部为小写。
myPromise
.then(function (result) {
// Once we receive JSON,
// turn it into a JSON object and return.
return JSON.parse(result);
})
.then(function (parsedJSON) {
// Once json has been parsed,
// get the email address and make it lowercase.
return parsedJSON.email.toLowerCase();
})
.then(function (emailAddress) {
// Once text has been made lowercase,
// print it to the console.
console.log(emailAddress);
}, function (err) {
// Something in the above chain went wrong?
// Print reject output.
console.error(err);
});
您可以在此处看到,尽管我们的初始调用是异步的,但也可以链接同步调用。 在每个代码resolve
里面的功能then
将被调用每一个返回时。 您还将注意到,此处为整个链指定了一个错误函数。 通过将其作为最后一个then
的reject
函数放置在链的末尾,链中任何调用reject
promise都将调用此函数。
现在,我们对承诺有了更多的信心,让我们结合上面的一个创建另一个。 我们将创建一个接收新的小写电子邮件地址的地址,然后(假装)将电子邮件发送到该地址。 这只是说明异步的示例,它可以是任何事情,例如与服务器联系以查看电子邮件是否在白名单上或用户是否登录。我们需要将电子邮件地址提供给新的诺言,但诺言不接受论点。 解决此问题的方法是将promise封装在一个确实起作用的函数中,如下所示:
var sendEmail = function (emailAddress) {
return new Promise(function (resolve, reject) {
// Pretend to send an email
// or do something else asynchronous
setTimeout(function () {
resolve('Email sent to ' + emailAddress);
}, 3000);
});
};
我们在这里使用setTimeout
调用来简单地伪造一个需要几秒钟才能异步运行的任务。
那么我们如何使用新的承诺创建功能呢? 好吧,由于then
使用的每个resolve
函数都应该返回一个函数,因此我们可以以与同步任务类似的方式使用它。
myPromise
.then(function (result) {
return JSON.parse(result);
})
.then(function (parsedJSON) {
return parsedJSON.email.toLowerCase();
})
.then(function (emailAddress) {
return sendEmail(emailAddress)
})
.then(function (result) {
// Outputs "Email sent to stuart@fakemail.biz"
console.log(result);
}, function (err) {
console.error(err);
});
让我们回顾一下该流程,以总结发生的情况。 我们最初的承诺myPromise
请求一段JSON。 当接收到JSON(我们不知道何时)时,我们将JSON转换为JavaScript对象并返回该值。
完成后,我们将电子邮件地址从JSON中删除,并将其小写。 然后,我们向该地址发送一封电子邮件,而我们又一次不知道它什么时候完成,但是当它完成时,我们会将成功消息输出到控制台。 看不见大量的嵌套。
结论
我希望这对Promises有所帮助,并为您提供了在JavaScript项目中开始使用它们的充分理由。 如果您想更详细地了解有关Promises的信息,请查看Jake Archibald关于该主题的出色的HTML5 Rocks文章 。
学习JavaScript:完整指南
我们已经建立了完整的指南,可以帮助您学习JavaScript ,无论您是刚开始作为Web开发人员还是想探索更高级的主题。
翻译自: https://code.tutsplus.com/tutorials/keeping-promises-with-javascript--cms-25056