1.什么是promise
promise 是抽象异步处理对象以及对其进行各类操做的组件。
2.表现的形式是什么样子的?
回调函数:getAsync("fileA.txt", function(error, result){ if(error){// 取得失败时的处理 throw error; } // 取得成功时的处理 });
使用promise进行异步处理:var promise = getAsyncPromise("fileA.txt"); promise.then(function(result){ // 获取文件内容成功时的处理 }).catch(function(error){ // 获取文件内容失败时的处理 });
与异步回调函数相比较:在使用promise进行一步处理的时候,咱们必须按照接口规定的方法编写处理代码。也就是说,除promise对象规定的方法(这里的 then 或 catch)之外的方法都是不可使用的, 而不会像回调函数方式那样能够本身自由的定义回调函数的参数,而必须严格遵照固定、统一的编程方式来编写代码。
3.如何使用?
目前大体有下面三种类型。
Constructor
Promise相似于 XMLHttpRequest,从构造函数 Promise 来建立一个新建新promise对象做为接口。
要想建立一个promise对象、可使用new来调用Promise的构造器来进行实例化。
var promise = new Promise(function(resolve, reject) { // 异步处理 // 处理结束后、调用resolve 或 reject });
Instance Method
对经过new生成的promise对象为了设置其值在 resolve(成功) / reject(失败)时调用的回调函数 可使用promise.then() 实例方法。
promise.then(onFulfilled, onRejected)
resolve(成功)时
onFulfilled 会被调用
reject(失败)时
onRejected 会被调用
onFulfilled、onRejected 两个都为可选参数。
promise.then 成功和失败时均可以使用。 另外在只想对异常进行处理时能够采用 promise.then(undefined, onRejected) 这种方式,只指定reject时的回调函数便可。 不过这种状况下 promise.catch(onRejected) 应该是个更好的选择。
promise.catch(onRejected)
Static Method
像 Promise 这样的全局对象还拥有一些静态方法。
包括 Promise.all() 还有 Promise.resolve() 等在内,主要都是一些对Promise进行操做的辅助方法。
function asyncFunction() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('Async Hello world');
}, 16);
});
}
asyncFunction().then(function (value) {
console.log(value); // => 'Async Hello world'
}).catch(function (error) {
console.log(error);
});
asyncFunction 这个函数会返回promise对象, 对于这个promise对象,咱们调用它的 then 方法来设置resolve后的回调函数, catch 方法来设置发生错误时的回调函数。
该promise对象会在setTimeout以后的16ms时被resolve, 这时 then 的回调函数会被调用,并输出 'Async Hello world' 。
4.promise的状态
用new Promise 实例化的promise对象有如下三个状态。
"has-resolution" - Fulfilled
resolve(成功)时。此时会调用 onFulfilled
"has-rejection" - Rejected
reject(失败)时。此时会调用 onRejecte
"unresolved" - Pending
既不是resolve也不是reject的状态。也就是promise对象刚被建立后的初始化状态等
关于上面这三种状态的读法,其中 左侧为在 ES6 Promises 规范中定义的术语, 而右侧则是在 Promises/A+ 中描述状态的术语
5.代码编写
function getURL(URL) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', 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(); }); } // 运行示例 var URL = "http://httpbin.org/get"; getURL(URL).then(function onFulfilled(value){ console.log(value); }).catch(function onRejected(error){ console.error(error); });
getURL 只有在经过XHR取得结果状态为200时才会调用 resolve - 也就是只有数据取得成功时,而其余状况(取得失败)时则会调用 reject 方法。
resolve(req.responseText) 在response的内容中加入了参数。 resolve方法的参数并无特别的规则,基本上把要传给回调函数参数放进去就能够了。 ( then 方法能够接收到这个参数值)
6.promise.resolve
通常状况下咱们都会使用 new Promise() 来建立promise对象,可是除此以外咱们也可使用其余方法。这里使用promise.resolve
例如:
new Promise(function(resolve){ resolve(42); });
在这段代码中的 resolve(42); 会让这个promise对象当即进入肯定(即resolved)状态,并将 42 传递给后面then里所指定的 onFulfilled 函数。
实际上, .then 中指定的方法调用是异步进行的。
var promise = new Promise(function (resolve){ console.log("inner promise"); // 1 resolve(42); }); promise.then(function(value){ console.log(value); // 3 }); console.log("outer promise"); // 2
因为JavaScript代码会按照文件的从上到下的顺序执行,因此最开始 <1> 会执行,而后是 resolve(42); 被执行。这时候 promise 对象的已经变为肯定状态,FulFilled被设置为了 42 。
下面的代码 promise.then 注册了 <3> 这个回调函数,这是本专栏的焦点问题。
因为 promise.then 执行的时候promise对象已是肯定状态,从程序上说对回调函数进行同步调用也是行得通的。可是即便在调用 promise.then 注册回调函数的时候promise对象已是肯定的状态,Promise也会以异步的方式调用该回调函数,这是在Promise设计上的规定方针。
所以 <2> 会最早被调用,最后才会调用回调函数 <3> 。
因为Promise保证了每次调用都是以异步方式进行的,因此咱们在实际编码中不须要调用 setTimeout 来本身实现异步调用。