Promise 对象的含义与基本用法
Posted shihaiying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise 对象的含义与基本用法相关的知识,希望对你有一定的参考价值。
㈠Promise 的含义
⑴Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
⑵所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
⑶从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
⑷Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
㈡Promise对象的特点
⑴对象的状态不受外界影响。
Promise
对象代表一个异步操作,它有三种状态:
①pending:进行中
②fulfilled :已经成功
③rejected:已经失败
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
⑵一旦状态改变,就不会再变,任何时候都可以得到这个结果。
promise状态改变:
①从pending变为fulfilled
②从pending变为rejected。
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)
㈢promise的缺点
⑴无法取消Promise
,一旦新建它就会立即执行,无法中途取消
⑵如果不设置回调函数,Promise
内部抛出的错误,不会反应到外部
⑶当处于pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
㈣基本用法
ES6 规定,Promise
对象是一个构造函数,用来生成Promise
实例。
下面代码创造了一个Promise
实例:
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
★Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
。
⑴resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
⑵reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
★Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
方法可以接受两个回调函数作为参数。
⑴第一个回调函数是Promise
对象的状态变为resolved
时调用
⑵第二个回调函数是Promise
对象的状态变为rejected
时调用。
⑶其中,第二个函数是可选的,不一定要提供。
⑷这两个函数都接受Promise
对象传出的值作为参数。
★下面是一个Promise
对象的简单例子:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, ‘done‘);
});
}
timeout(100).then((value) => {
console.log(value);
});
⑴上面代码中,timeout
方法返回一个Promise
实例,表示一段时间以后才会发生的结果。
⑵过了指定的时间(ms
参数)以后,Promise
实例的状态变为resolved
,就会触发then
方法绑定的回调函数。
★Promise 新建后就会立即执行
let promise = new Promise(function(resolve, reject) {
console.log(‘Promise‘);
resolve();
});
promise.then(function() {
console.log(‘resolved.‘);
});
console.log(‘Hi!‘);
// Promise
// Hi!
// resolved
⑴上面代码中,Promise 新建后立即执行,所以首先输出的是Promise
。
⑵然后,then
方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved
最后输出。
★异步加载图片的例子
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error(‘Could not load image at ‘ + url));
};
image.src = url;
});
}
⑴上面代码中,使用Promise
包装了一个图片加载的异步操作。
⑵如果加载成功,就调用resolve
方法,失败就调用reject
方法。
★用Promise
对象实现的 Ajax 操作的例子。
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log(‘Contents: ‘ + json);
}, function(error) {
console.error(‘出错了‘, error);
});
⑴上面代码中,getJSON
是对 XMLHttpRequest 对象的封装,用于发出一个针对 JSON 数据的 HTTP 请求,并且返回一个Promise
对象。
⑵需要注意的是,在getJSON
内部,resolve
函数和reject
函数调用时,都带有参数。
⑶如果调用resolve
函数和reject
函数时带有参数,那么它们的参数会被传递给回调函数。
⑷reject
函数的参数通常是Error
对象的实例,表示抛出的错误;
⑸resolve
函数的参数除了正常的值以外,还可能是另一个 Promise 实例
示例:
const p1 = new Promise(function (resolve, reject) {
// ...
});
const p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);
})
①上面代码中,p1
和p2
都是 Promise 的实例,但是p2
的resolve
方法将p1
作为参数
即一个异步操作的结果是返回另一个异步操作。
②注意,这时p1
的状态就会传递给p2
,也就是说,p1
的状态决定了p2
的状态。
③如果p1
的状态是pending
,那么p2
的回调函数就会等待p1
的状态改变;
④如果p1
的状态已经是resolved
或者rejected
,那么p2
的回调函数将会立刻执行。
★下面代码中
⑴p1
是一个 Promise,3 秒之后变为rejected
。
⑵p2
的状态在 1 秒之后改变,resolve
方法返回的是p1
。
⑶由于p2
返回的是另一个 Promise,导致p2
自己的状态无效了,由p1
的状态决定p2
的状态。
⑷所以,后面的then
语句都变成针对后者(p1
)。
⑸又过了 2 秒,p1
变为rejected
,导致触发catch
方法指定的回调函数。
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error(‘fail‘)), 3000)
})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2
.then(result => console.log(result))
.catch(error => console.log(error))
// Error: fail
⑹注意,调用resolve
或reject
并不会终结 Promise 的参数函数的执行
★下面代码中
⑴调用resolve(1)
以后,后面的console.log(2)
还是会执行,并且会首先打印出来。
⑵这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
★一般来说,调用resolve
或reject
以后,Promise 的使命就完成了,
后继操作应该放到then
方法里面,而不应该直接写在resolve
或reject
的后面。
所以,最好在它们前面加上return
语句,这样就不会有意外。
new Promise((resolve, reject) => {
return resolve(1);
// 后面的语句不会执行
console.log(2);
})
来自:http://es6.ruanyifeng.com/?search=fetch&x=0&y=0#docs/promise
以上是关于Promise 对象的含义与基本用法的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段12——JavaScript的Promise对象
VSCode自定义代码片段12——JavaScript的Promise对象