JavaScript承诺入门

异步代码对于执行耗时的任务很有用,但是当然,它并非没有缺点 。 异步代码使用回调函数来处理其结果,但是回调函数无法返回典型JavaScript函数可以返回的值

因此,它们不仅剥夺了我们控制功能执行的能力,而且使错误处理变得有些麻烦。 这是Promise对象出现的地方,因为它旨在填补异步编码中的一些缺陷

从技术上讲, Promise是JavaScript中的标准内部对象 ,这意味着它内置于JavaScript中 。 它用于表示异步代码块最终结果 (或代码失败的原因),并具有控制异步代码执行的方法。

句法

我们可以使用new关键字创建Promise对象的实例

new Promise(function(resolve, reject) {} );

作为参数传递Promise()构造函数的函数称为executor 。 它保存异步代码,并具有两个Function类型的参数 ,称为resolvereject函数(稍后将对此进行详细介绍)。

Promise对象的初始状态称为未决 。 在这种状态下,异步计算的结果不存在

计算成功后 ,初始暂挂状态将变为已完成状态。 在这种状态下,计算结果可用。

万一异步计算失败Promise对象将从其初始挂起状态移至拒绝状态。 在这种状态下,可以使计算失败原因 (即错误消息)可用。

为了从待处理状态变为完成状态, 调用resolve() 。 为了从待处理状态变为拒绝状态,请调用reject()

承诺的三种状态

当状态从未变为完成时 ,将执行Promise对象的then方法的事件处理程序。 并且,当状态从未变为拒绝时 ,将执行Promise对象的catch方法的事件处理程序。

例子1
“未承诺”代码

假设有一个hello.txt文件,其中包含“ Hello”字样。 这是我们可以编写AJAX请求以获取该文件显示其内容的方式 ,而无需使用Promise对象:

function getTxt() {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'hello.txt');
    xhr.overrideMimeType('text/plain');
    xhr.send();
    xhr.onload = function() {
        try {
            switch (this.status) {
                case 200:
                    document.write(this.response);
                    break;
                case 404:
                    throw 'File Not Found';
                default:
                    throw 'Failed to fetch the file';
            }
        } catch (err) {
            console.log(err)
        }
    };
}

getTxt();

如果已成功获取文件的内容,即响应状态代码为200 ,则将响应文本写入文档中 。 如果找不到文件(状态404) ,则会引发“找不到文件”错误消息 。 否则,将抛出一条一般错误消息,指示获取文件失败。

“承诺”代码

现在,让我们承诺上面的代码

function getTxt() {
    return new Promise(function(resolve, reject) {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', 'hello.txt');
        xhr.overrideMimeType('text/plain');
        xhr.send();
        xhr.onload = function() {
            switch (this.status) {
                case 200:
                    resolve(this.response);
                case 404:
                    reject('File Not Found');
                default:
                    reject('Failed to fetch the file');
            }
        };
    });
}

getTxt().then(
    function(txt) {
        document.write(txt);
    }).catch(
    function(err) {
        console.log(err);
    });

现在,对getTxt()函数进行了编码,以返回Promise对象的新实例 ,并且其执行程序函数保存以前的异步代码。

响应状态代码为200时 ,通过调用resolve() 实现 Promise (响应作为resolve()的参数传递)。 当状态代码是404或一些其它的Promise 使用 拒绝 reject()具有作为参数的相应的错误消息reject()

Promise 实现时 ,将运行then()方法的处理程序。 它的参数是resolve()传递的参数 。 在事件处理程序内部,将响应文本(作为参数接收) 写入文档

Promise拒绝时catch()方法的事件处理程序将运行,并记录error

上面的Promisified版本的代码的主要优点错误处理 。 而不是像未承诺的版本那样抛出未捕获的异常,而是返回并记录适当的故障消息

但是,不仅返回 失败消息,而且返回 异步计算结果,这对于我们来说确实是有利的。 为此,我们需要扩展示例。

例子2
“未承诺”代码

我不仅要显示来自hello.txt的文本, hello.txt希望将其与“世界”一词结合起来,并在 2秒钟的超时后将其显示在屏幕上。 这是我使用的代码:

function getTxt() {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', 'hello.txt');
    xhr.overrideMimeType('text/plain');
    xhr.send();
    xhr.onload = function() {
        try {
            switch (this.status) {
                case 200:
                    document.write(concatTxt(this.response));
                    break;
                case 404:
                    throw 'File Not Found';
                default:
                    throw 'Failed to fetch the file';
            }
        } catch (err) {
            console.log(err)
        }
    };
}

function concatTxt(res) {
    setTimeout(function() {
        return (res + 'World')
    }, 2000);
}

getTxt();

在状态码200上, concatTxt()函数将响应文本与“世界”字连接起来,然后再将其写入文档。

但是,此代码无法按需工作setTimeout()回调函数无法返回串联的字符串 。 未打印到文档的内容是undefined因为那concatTxt()返回的内容

“承诺”代码

因此,为了使代码正常工作,让我们对上述代码进行 concatTxt() ,其中包括concatTxt()

function getTxt() {
    return new Promise(function(resolve, reject) {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', 'hello.txt');
        xhr.overrideMimeType('text/plain');
        xhr.send();
        xhr.onload = function() {
            switch (this.status) {
                case 200:
                    resolve(this.response);
                case 404:
                    reject('File Not Found');
                default:
                    reject('Failed to fetch the file');
            }
        };
    });
}

function concatTxt(txt) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(txt + ' World');
        }, 2000);
    });
}

getTxt().then(
    (txt) = > {
        return concatTxt(txt);
    }).then(
    (txt) = > {
        document.write(txt);
    }).catch(
    (err) = > {
        console.log(err);
    });

就像getTxt()concatTxt()函数也返回一个新的Promise对象,而不是串联的文本。 concatTxt()返回的Promise setTimeout()回调函数中解析

在上述代码的结尾附近,第一个then()方法的事件处理程序在满足 getTxt()Promise getTxt()成功获取文件getTxt()时运行。 在该处理程序内, concatTxt()返回concatTxt()返回Promise

满足 concatTxt()返回PromiseconcatTxt()两秒超时结束并且以连接字符串作为参数调用resolve()then() ,第二个then()方法的事件处理程序将运行。

最后, catch() 捕获来自两个Promises的所有异常和失败消息

在此承诺版本中,“ Hello World”字符串将成功打印到文档中。


翻译自: https://www.hongkiat.com/blog/javascript-promise-object/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值