这篇文章记录原生ajax的使用以及Promise
提示:以下是本篇文章正文内容,下面案例可供参考
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
// 1创建XMLHttpRequest对象
var xmlhttp
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else { // 兼容早期浏览器
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2发送请求
xmlhttp.open('GET', url, true)
xmlhttp.send()
// 3服务端响应
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var obj = JSON.parse(xmlhttp.responseText)
successCallback && successCallback(obj)
} else if (xmlhttp.readyState === 4 && xmlhttp.status === 404) {
failCallback && failCallback('Not Found')
}
}
// Ajax原理
var url = 'xxxxxx'
function Ajax(url, callback) {
// 1创建XMLHttpRequest对象
var xmlhttp
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else { // 兼容早期浏览器
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2发送请求
xmlhttp.open('GET', url, true)
xmlhttp.send()
// 3服务端响应
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var obj = JSON.parse(xmlhttp.responseText)
callback(obj)
}
}
}
Ajax('url1', (res) => {
console.log(res)
Ajax('url2', (res) => {
console.log(res)
Ajax('url3', (res) => {
console.log(res)
})
})
})
以上案例中最后的调用会产生回调地狱,这导致代码可读性非常低,下面可以使用Promise进行改造
ECMAscript 6 原生提供了 Promise 对象。
Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。
Promise 对象有以下两个特点:
1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
pending: 初始状态,不是成功或失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果
。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固
了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise 优缺点
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消
Promise,一旦新建它就会立即执行
,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
要想创建一个 promise 对象、可以使用 new 来调用 Promise 的构造器来进行实例化。下面是创建 promise 的步骤:
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
两个参数:
resolve
异步操作成功时调用
reject
异步操作不通过时调用
执行异步操作后调用
.then
异步操作完成后执行,接受两个函数作为参数,第一个是成功时执行,第二个是失败时执行
.catch
异步操作失败时在此捕获错误
.finally
无论结果如何,异步操作结束后都会执行
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('imooc')
// resolve('成功')
reject('失败')
}, 1000)
}).then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
可通过尝试以下案例查看输出结果具体了解Promise的使用
let p1 = new Promise((resolve, reject) => {
resolve(1)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 1000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(3)
}, 1000)
})
console.log(p1)
console.log(p2)
console.log(p3)
setTimeout(() => {
console.log(p2)
}, 2000)
setTimeout(() => {
console.log(p3)
}, 2000)
p1.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
p2.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
p3.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
p3.catch((err) => {
console.log(err)
})
代码如下(示例):
// 改造Ajax异步状态
function Ajax(url, successCallback, failCallback) {
// 1创建XMLHttpRequest对象
var xmlhttp
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else { // 兼容早期浏览器
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2发送请求
xmlhttp.open('GET', url, true)
xmlhttp.send()
// 3服务端响应
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var obj = JSON.parse(xmlhttp.responseText)
successCallback && successCallback(obj)
} else if (xmlhttp.readyState === 4 && xmlhttp.status === 404) {
failCallback && failCallback('Not Found')
}
}
}
// 改造
function getPromise(url) {
return new Promise((resolve, reject) => {
Ajax(url, (res) => {
resolve({ data: res, msg: '成功' })
}, (err) => {
reject({ err: err, data: '', msg: '失败' })
})
})
}
getPromise('url')
.then((res) => {
console.log(res)
return getPromise('url1')
}, (err) => {
console.log(err)
return getPromise('url1')
}).then((res) => {
console.log(res)
return getPromise('url2')
}, (err) => {
console.log(err)
return getPromise('url2')
}).then((res) => {
console.log(res)
}).catch(err => {
console.log(err)
})
一些注意事项
then、catch 和 finally 序列顺序颠倒,效果完全一样。但不建议这样做,最好按 then-catch-finally 的顺序编写程序。
除了 then 块以外,其它两种块能多次使用,finally 与 then 一样会按顺序执行,但是 catch 块只会执行第一个,除非 catch 块里有异常。所以最好只安排一个 catch 和 finally 块。
then 块默认会向下顺序执行,return 是不能中断的,可以通过 throw 来跳转至 catch 实现中断。
当需要多次顺序执行异步操作的时候,例如,如果想通过异步方法先后检测用户名和密码,需要先异步检测用户名,然后再异步检测密码的情况下就很适合 Promise。
Promise 不是一种将异步转换为同步的方法,Promise 只不过是一种更良好的编程风格。
这里只是学习Promise的一些基本使用,还有一些方法没有列出来,更多的教程建议查看: 菜鸟教程