博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js异步操作与promise对象使用
阅读量:6337 次
发布时间:2019-06-22

本文共 4621 字,大约阅读时间需要 15 分钟。

今天我想说说说promise对象,说到这个对象就不能不提提异步操作,那么什么是异步操作,什么又是同步操作?

同步与异步操作区别

同步操作的意思是在我们执行某个耗时比较长的操作的时候,下面的代码就会等待上面的代码执行完毕然后执行。说白了代码是顺序往下执行,某些操作执行的时间顺序和代码所在的行的顺序是相同的。请看下面获取一个txt文件的例子。

同步程序示例
首先,我们利用node先搭建一个服务器环境,默认获取1.html静态文件。代码如下:

let http = require('http');let url = require('url');let path = require('path');let fs = require('fs');http.createServer((req, res) => {    var pathname = __dirname + url.parse(req.url).pathname;    if (path.extname(pathname) === "") {        pathname += "/";    }    if (pathname.charAt(pathname.length - 1) === "/") {        pathname += '1.html'    }    fs.exists(pathname, exists => {        if (exists) {            switch (path.extname(pathname)) {                case ".html":                    res.writeHead(200, { 'Content-type': "text/html" });                    break;                case ".js":                    res.writeHead(200, { 'Content-type': "text/javascript" });                    break;                case ".jpg":                    res.writeHead(200, { 'Content-type': "image/jpeg" });                    break;                case ".png":                    res.writeHead(200, { 'Content-type': "image/png" });                case ".txt":                    res.writeHead(200, { 'Content-type': "text/plain" });                    break;                case ".css":                    res.writeHead(200, { 'Content-type': "text/css" });                    break;                default:                    ead                    res.writHead(200, { 'Content-type': "application/octet-stream" })            }            fs.readFile(pathname, (err, data) => {                if (err) {                    console.log('read file error');                } else                    res.end(data);            })        }    })}).listen(3000);console.log('server is runing...')

我们要从服务器用ajax获取txt文本数据。然后从客户端获取数据,如果这个操作是一个同步操作。如下所示

客户端获取数据代码

function showTxt(txt) {            console.log(txt);        }         function getDocuments(url, cb) {            let xhr = new XMLHttpRequest();             xhr.open("GET", url,false);             xhr.send();、              cb(xhr.responseText);                   }        getDocuments('1.txt', showTxt);        console.log("我是获取文件之后执行的代码");

结果如下:

图片描述
等这个获取文件这个操作执行完后,就会顺序执行接下来的代码。
这样的操作有什么问题呢?如果这个获取文件的代码耗时比较长,我们的程序就会卡死,下面的代码就不会执行下去,必须等获取文件代码执行完毕,解决问题的方法就是异步获取文件。那么什么是异步操作呢?说白了就是把获取文件的操作挂到另外一个线程,先执行后面的代码,上面的获取文件代码不会阻塞下面代码的运行。这两个操作是同时进行的。在以前,通常,如果是异步获取数据的,那么执行这个费时的获取数据操作时,会指定一个回调函数,当获取文件成功时触发处理结果的回调函数。在这个过程中,下面其他的代码会同时进行。把刚才获取文件的代码改成异步,请看下面代码。
异步获取数据程序示例

function showTxt(txt) {            console.log(txt);        }        function getDocuments(url, cb) {            let xhr = new XMLHttpRequest();            xhr.open("GET", url);            xhr.send();            xhr.onreadystatechange = () => {                if (xhr.status === 200 && xhr.readyState == 4) {                    cb(xhr.responseText);                } else if (xhr.readyState === 4 && xhr.status !== 200) {                    console.log(`${xhr.status}get error`);                }            };        }        getDocuments('1.txt', showTxt);        console.log("我是获取文件后执行的代码");
![图片描述][2]

可以看出先执行了下面的代码然后执行了ajax获取文件回调函数里面的代码,证明了下面的其他操作的代码会与获取文件操作同时执行。这就是异步操作与同步操作的区别

promise对象有什么用处?

由上面示例可以看到如果是一个异步操作的代码,通常,我们就需要为它指定回调函数,例如上面的代码回调函数就是onreadystatechange当它的状态码变成4,收到服务器响应,我们拿到数据后再执行下步操作,先把它挂起来,让下面的的代码运行。但是如果因果关系变得复杂,回调事件变得很多,我们的代码就会变得十分像一个向右的金字塔结构不利于阅读。

promise对象巧妙的解决了这个问题,把回调函数变成了链式调用,更加符合代码书写习惯。那么如何使用它呢?

请看下面例子

function getTxt(url) {            let p = new Promise((resolve, reject) => {                let xhr = new XMLHttpRequest();                xhr.open("GET", url);                xhr.send();                xhr.onreadystatechange = () => {                    if (xhr.readyState !== 4) {                        return;                    }                    if (xhr.status === 200) {                        resolve(xhr.responseText);                    } else {                        reject(`${xhr.status}get error`);                    }                }            });            return p;        }        getTxt('1.txt').then(showTxt).catch((error) => {            console.log(error);        });        console.log('我是写在异步操作之后的操作')

总结

通过控制台打印的内容可以看出,跟使用回调函数在结果上并没有什么异同。但是代码结构更加清晰化,并且可以catch到错误信息。
1.先new 一个promise对象,然后给它的参数传递一个回调函数进去,回调函数里面有两个参数resolve,reject都是函数。
2.resolve函数是把异步状态变成成功,可以把异步结果作为它的参数传递到then的回调函数参数中,而then方法会在promise状态成功时候调用;3.reject函数可以把promise状态变成失败,当异步请求状态失败时调用,可以传递出去错误信息,这个会触发promise对象上的catch方法,通过promise对象的catch方法的回调函数的参数捕获该错误信息。最后返回该promise对象实现链式调用。这就是promise对象的基本用法。

4.当然它还有all, race,resolve,reject等各种实例方法和静态方法,不过上面的用法时最经常见到的,最基础的。

转载地址:http://alaoa.baihongyu.com/

你可能感兴趣的文章
Docker配置网络
查看>>
yum安装cacti
查看>>
Zabbix通过Orabbix监控Oracle
查看>>
linux双线双网卡双IP双网关设置方法
查看>>
免费站长工具大全
查看>>
Android Studio第十期 - 招商银行两种支付方式
查看>>
详细解读Jquery各Ajax函数:$.get(),$.post(),$.ajax(),$.getJSON()
查看>>
DHCP在企业网中的应用
查看>>
2008的共享服务器搭建
查看>>
Linux常用的命令
查看>>
已经不再更新新浪、网易及CSDN博客了!
查看>>
虚拟机克隆后修改mac地址和ip地址
查看>>
解决数据库乱码问题【转】
查看>>
注册表操作类【原】
查看>>
清远市第一中学大学城网
查看>>
环回接口(loopback interface)的新认识
查看>>
LINQ之路13:LINQ Operators之连接(Joining)
查看>>
数据结构--队列之C数组实现
查看>>
通过创建存储过程显示数据表的字段名和说明
查看>>
html5-css动画-2d
查看>>