用JavaScript兑现承诺

通过JavaScript的流行和最近的改进,JavaScript越来越成为Web程序员的最佳朋友。 和所有最好的朋友一样,JavaScript恪守诺言。

现在听起来有些奇怪,但这是事实。 当前大多数浏览器都支持Promise对象 。 一个promise就像一个函数一样,它代表了一段代码或您希望在将来某个时刻执行的任务。

这就是诺言的样子。

var myPromise = new Promise(function (resolve, reject) {
    // Task to carry out goes here.
});

您可以在此处看到,当我们创建一个Promise时,我们给它一个参数,该参数是一个函数,其中包含我们希望在将来某个时刻执行的代码。 您可能还已经注意到传递给promise, resolvereject的函数中的两个参数。 这些也是功能,是我们告诉Promise是否已完成承诺的方法。 这是您将如何使用它们:

var myPromise = new Promise(function (resolve, reject) {
    if (true) {
        resolve('Hello Tuts+ fans!');
    } else {
        reject('Aww, didn\'t work.');
    }
});

由于if语句将始终为真,因此该承诺显然总是会得到解决。 这只是出于学习目的,我们将在以后做一些更现实的事情,但是请想象一下,用一小段不确定100%确定会起作用的代码替换true

现在我们已经创建了一个承诺,我们如何使用它? 好吧,我们需要告诉它那些resolvereject函数是什么。 我们通过使用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中。 通过将其放在此处,我们基本上是在说:“嘿,一段代码,我现在必须走了,但是稍后我会给您打电话,告诉您何时执行。答应您这样做并告诉我完成后?” 代码会说:“是的,当然。我保证。”

在上面的代码段中要注意的重要事情是resolvereject函数的调用。 请记住,这是我们兑现我们的承诺:代码已成功执行或未成功执行的方式。 否则,我们永远不会知道。

使用基本示例中的相同代码,我们可以看到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将被调用每一个返回时。 您还将注意到,此处为整个链指定了一个错误函数。 通过将其作为最后一个thenreject函数放置在链的末尾,链中任何调用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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值