继续昨天promise
promise.then()成功和失败时都可以使用。异常的时候调用promise.catch(onRejected)
像promise这样的全局对象还拥有一些静态方法。包括promise.all()还有promise.resolve()等在内,主要都是一些对promise进行操作的辅助方法。
用new promise实例化的promise对象有以下三个状态。其中,左侧为ES6 promise规范中定义的术语,而右侧是在promise/A+中描述状态的术语。
(1)“has-resolution” - Fulfilled: resolve(成功)时。此时会调用onFulfilled
(2)“has-rejection” - Rejected: reject(失败)时。此时会调用onRejected
(3)“unresolved” - Pending: 既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态等。
promise对象的状态,从pending转换为Fulfilled或Rejected之后,这个promise对象的状态就不会在发生任何变化。也就是说,promise与Event等不同,在.then后执行的函数可以肯定地说只会被调用一次。
基本流程
1.new promise(fn)返回一个promise对象
2.在fn中指定异步等处理
处理结果正常的话,调用resolve(处理结果值)
处理结果错误的话,调用reject(error对象)
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);
});
- 本质上还是回调函数。将回调函数用promise对象包装一下。
- resolve方法的参数并没有什么特别的规则,基本上把要传给回调函数参数放进去就可以了。(then方法可以接收到这个参数值)
- 传给reject的参数也没有什么特殊的限制,一般只要是error对象(或者继承自error对象)就可以。
- 其实.catch只是promise.then(undifined, onRejected)的别名而已。一般来说使用.catch来将resolve和reject处理分开来写是比较推荐的做法。
(上面都是“别人的东西”,谁实话promise这个东西真的好难理解,看着看着我又忘了回调函数的过程。。)
后来看了这篇文章对于理解promise很有帮助:https://www.cnblogs.com/lvdabao/p/es6-promise-1.html
这次换更通俗的方法理解。
首先是promise对象的创建。
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('随便什么数据');
}, 2000);
});
(1)构造函数传入的参数是一个函数(function(resolve,reject){});
(2)这个函数的参数是resolve和reject。我们可以暂时将他理解为成功和失败。(但其实是将promise状态进行转变成fulfilled和rejected)
(3)这个函数中可以放置异步操作。
(4)resolve和reject可以将他们后面的数据传递给then()(如resolve(‘随便什么数据’)可以将‘随便什么数据’传递下去)
(5)catch方法本质和then是一样的(catch = then(undefined,reject))并且使用catch有一个好处是:如果代码本身有错误而且没有使用promise,可能会在报错的地方卡住无法继续运行,而使用了promise后异常会一直传递到catch中被catch捕获
(6)all方法的使用:
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
(7)race方法的使用:
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
谁先执行完成谁先进入then
用promise.all来执行,all接受一个数组参数,里面的值最终都返回promise对象。这样三个异步操作的并行执行,等他们都执行完才会进到then里面。
promise相对于传统的callback()进行回调好处是:promise是链式的结构,不像callback会出现多层嵌套导致回调地狱。
算法题
实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
这题我只能想到用循环的方式来进行幂指数的运算,如果用每次自身翻倍的话可以使时间复杂度降到O(logn),但是对于n是奇数的情况判断比较复杂。
参考了题解之后看到这种方法:
class Solution {
public double myPow(double x, int n) {
if(x == 0) return 0;
if(n == 0) return 1;
double res = 1;
long b = n;
if(b < 0){
x = 1/x;
b = -b;
}
while(b > 0){
if((b & 1) == 1) res *= x;
x *= x;
b >>= 1;
}
return res;
}
}
思路是将指数n转化成二进制
这里要注意的是当n小于0时,n = -n可能会导致越界,所以现将n存放进long b中。