什么是异步
异步(async)
是相对于同步(sync)
而言的,很好理解。
同步
就是一件事一件事的执行。只有前一个任务执行完毕,才能执行后一个任务。
何时需要异步
- 在可能发生等待的情况
- 等待过程中不能像alert一样阻塞程序的时候
- 因此,所有的“等待的情况”都需要异步
- 一句话总结就是需要等待但是又不能阻塞程序的时候需要使用异步
那么常见的异步模式有哪些呢?
- 回调函数
- 事件监听
- 发布/订阅模式(又称观察者模式)
- promise
总结:异步就是不等待结果的代码,JS 引擎不能同时做两件事
Promise
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。
语法:
new Promise( function(resolve, reject) {...} /* executor */ );复制代码
Promise
对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知 的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法 可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结 果的promise对象
一个 Promise有以下几种状态
-
pending : 初始状态,既不是成功,也不是失败状态。
-
fulfilled : 意味着操作成功完成。
-
rejected : 意味着操作失败。
Pending 状态的 Promise 对象可能触发Fulfilled 状态并传递一个值给相应的状态处理方法,也可能触发失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then
方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo');
}, 300);
});
promise1.then(function(value) {
console.log(value);
// expected output: "foo"
});
console.log(promise1);
// expected output: [object Promise]
复制代码
参考文档
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://javascript.ruanyifeng.com/advanced/promise.html
举个栗子_(:з」∠)_
<script>
function ajax(URL) {
var joking = new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('post', URL, true);
req.onload = function () {
if (req.status === 200) {
resolve(req.responseText);
} else {
reject(new Error(req.statusText));
}
};
req.onerror = function () {
reject(new Error(req.statusText));
};
req.send();
});
return joking;
}
var URL = "/test/promise.php";
ajax(URL).then(function onFulfilled(value){
document.write('内容是:' + value);
}).catch(function onRejected(error){
document.write('错误:' + error);
});
</script>复制代码
因为
和 Promise.prototype.then
方法返回promise 对象, 所以它们可以被链式调用。Promise.prototype.catch
上面代码中,resolve 方法和 reject 方法调用时,都带有参数。它们的参数会被传递给回调函数。reject 方法的参数通常是 Error 对象的实例。
当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)利用箭头函数进阶写法如下:
ajax(URL).then(
(value) => {
document.write('内容是:' + value);
},
(error) => {
document.write('错误:' + error);
}
)
复制代码
jQuery Defered
还是举栗子吧
var dtd = $.Deferred(); // 新建一个Deferred对象
var wait = function(dtd){
var tasks = function(){
alert("执行完毕!");
dtd.reject(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
return dtd;
};
$.when(wait(dtd))
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!");
});
复制代码
还是去这里看吧!
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html
async/await
async function
声明用于定义一个返回
AsyncFunction
对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的
Promise
返回其结果。但是如果你的代码使用了异步函数,它的语法和结构会更像是标准的同步函数。你还可以使用 异步函数表达式 来定义异步函数。
function sd() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
var result = await sd();
console.log(result);
// expected output: 'resolved'
}
asyncCall();复制代码
By Nidhogg·D·Joking