学习笔记 JavaScript ES6 异步编程Promise

Promise,ES里面对异步操作的第一种方案!

学习Promise,让异常操作变得优雅~~~

Promise的精髓在于异步操作的状态管理~

一个Promise最基本用法,他的参数是一个方法,这个方法里有两个参数,一个是异步操作执行成功的回调,一个是失败的回调:

// 第一个参数resolve表示异步操作执行成功时的回调函数
// 第二个参数reject表示执行失败的回调函数
let p = new Promise((resolve,reject) => {
    setTimeout(() => {
        console.log('Hello~')
         if(true) {
             resolve() // 执行这个方法时,会输出'成功'
         } else {
             reject() // 执行这个方法时,会输出'失败'
         }
    }, 1000);
    // then可以有两个函数参数,第一个参数必须
    // 第一个参数是异步执行成功时调用
    // 第二个参数是异步执行失败时调用
}).then(() => { 
    console.log('成功');
}, () => {
    console.log('失败');
}) 

传参数的例子:

let p = new Promise((resolve,reject) => {
    setTimeout(() => {
        console.log('Hello~')
         if(true) {
             resolve('成功')
         } else {
             reject('失败')
         }
    }, 1000);
}).then(res => { 
    console.log(res);
}, res => {
    console.log(res);
}) 

Promist内部的代码如果不是异步的,也会立刻执行,如:

let p = new Promise((resolve, reject) => {
    console.log(1)
})
console.log(2)

-----
1
2

看看下面这个执行顺序,先执行“宏”任务,再执行“微”任务,这个“微”任务是异步操作里的一个概念,then是promise的一个相关任务,

let p = new Promise((resolve, reject) => {
    console.log(1)
    resolve()
})
console.log(2)
p.then(res => {
    console.log(3)
})

------
1
2
3

学习笔记 JavaScript ES6 异步编程Promise_第1张图片看一下这几种状态的输出:

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);

------------------------------------------------------------------------------------------------------
下面的2,3在输出时,promise不会等待,而是直接执行,所以状态是pendding,4,5是因为等待了2秒,把程序都执行结束了,所以状态是fulfilled以及rejected
1、Promise {: 1}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: 1
2、Promise {}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"3[[PromiseResult]]: 2
3、Promise {}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: 3
4、Promise {: 2}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: 2
5、Promise {: 3}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: 3

基于上面代码继续完善then():

then里面的失败,可以在then的第二个参数里写失败,也可以直接用.catch()

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);
})

p1.then(res => {
    console.log(res)
})
p2.then(res => {
    console.log(res);
})
p3.catch(err => {
    console.log(err);
})

------
1
2
3

Promise的状态是不可逆的:

// 先调用的成功,即便之后再调用失败,也无法改变之前的状态
let p = new Promise((resovle,reject) => {
    resovle(1)
    reject(2)
})
p.then(res => {
    console.log(res);
},err => {
    console.log(err)
})

------
1

对之前学的callback hell进行改造: (先来写一个很容易理解的例子,后面再写更炫的例子)

function ajax(url, callback) {
    var xmlhttp;
    // 1、创建XMLHttpRequest对象
    // window.XMLHttpRequest这个对象存在,说明当前浏览器是IE7+或chrome
    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)
      }
    };
  }

new Promise((resolve, reject) => {
    ajax('http://jsonplaceholder.typicode.com/users', res => {
        console.log(res);
        resolve()
    })
}).then(res => {
    console.log('a成功')
    return new Promise((resolve, reject) => {
        ajax('http://jsonplaceholder.typicode.com/users', res => {
            console.log(res);
            resolve()
        })
    })
}).then(res => {
    console.log('b成功')
    return new Promise((resolve, reject) => {
        ajax('http://jsonplaceholder.typicode.com/users', res => {
            console.log(res);
            resolve()
        })
    })
}).then(res => {
    console.log('c成功');
})

-------------------------------------------------------------------
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
a成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
b成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
c成功

上面代码中,then().then()属于链式操作,return new Promise的return一定要加,如果不加的话相当于对一个空的promise执行了then(),不加return返回结果是错误的样子:没有按我们想要的顺序执行

------------------------------------------------------------
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
a成功
b成功
c成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

把上面的代码改造一下,变成更简洁、更炫的:


function ajax(url, callback) {
    var xmlhttp;
    // 1、创建XMLHttpRequest对象
    // window.XMLHttpRequest这个对象存在,说明当前浏览器是IE7+或chrome
    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)
      }
    };
  }
function getPromise(url) {
    return new Promise((resolve, reject) => {
        ajax(url, res => {
            resolve(res)
        })
    })
}

// 链式操作可以直接换行
getPromise('http://jsonplaceholder.typicode.com/users')
.then(res => {
    console.log('a成功');
    console.log(res)
    return getPromise('http://jsonplaceholder.typicode.com/users')
}).then(res => {
    console.log('b成功');
    console.log(res)
    return getPromise('http://jsonplaceholder.typicode.com/users')
}).then(res => {
    console.log('c成功');
    console.log(res);
})

---------------------------------------------------------------------------
a成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
b成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
c成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

 基于上面代码,再把请求失败的操作完善一下:

下面代码的写法注意一下:

// 这种写法的意思是当有参数传递了,再去调用 
successCallback && successCallback(obj)

注意看下面程序的注释 


function ajax(url, successCallback, failCallback) {
    var xmlhttp;
    // 1、创建XMLHttpRequest对象
    // window.XMLHttpRequest这个对象存在,说明当前浏览器是IE7+或chrome
    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(xmlhttp.status)
      }
    }
  }
function getPromise(url) {
    return new Promise((resolve, reject) => {
        ajax(url, res => { // 成功的情况
            resolve(res)
        }, err => { // 失败的情况
            reject(err) 
        })
    })
}

// 链式操作可以直接换行
getPromise('a.json')
.then(res => {
    console.log('a成功');
    console.log(res)
    return getPromise('http://jsonplaceholder.typicode.com/users')
}, err =>{
    console.log(err); // 这里执行后,没有return Promise,所以下面输入undefined
}).then(res => { // 这里能被执行,因为上面没有return Promise,所以默认返回空的Promise
    console.log('b成功');
    console.log(res)
    return getPromise('http://jsonplaceholder.typicode.com/users')
}).then(res => { //
    console.log('c成功');
    console.log(res);
})

-------------------------------------------------------------
404
b成功
undefined
c成功
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

 如果对失败进行统一的处理:

// 链式操作可以直接换行
getPromise('a.json')
.then(res => {
    console.log('a成功');
    return getPromise('http://jsonplaceholder.typicode.com/users')
}).then(res => {
    console.log('b成功');
    return getPromise('http://jsonplaceholder.typicode.com/users')
}).then(res => {
    console.log('c成功');
}).catch(err => {
    console.log(err);
})

------------------------------------------------------------------------
404 // a.json不存在 ,所以直接进入到最下面的catch里,上面的b,c就不会执行了

你可能感兴趣的:(学习笔记,JavaScript,ES6,javascript,前端,ecmascript)