promise (Es6)

1.什么是Promise?

promise是一个对象,可以获取异步操作的消息
Promise对象是一个构造函数,用来生成Promise实例

2.作用

解决异步请求请求问题
1.传统方式解决异步,用回调函数,事件
ajax(url, {//登录获取token,
ajax(url, {//获取用户信息,
ajax(url{//获取相关消息)}
}
axios就是一个基于 Promise 来管理 http 请求代码封装库

3.特点

1.对象的状态不受外界影响。
prosime有三个状态,penfing进行中,fulfilled成功,rejectes失败。只有异步操作的结果可以决定当前是哪一种状态。

2.一旦状态改变,就不会再变
promise对象的状态改变只有从进行中—->成功,进行中—->失败。状态凝固了,就不会再变

4.基本用法以及练习题

4.1.基本用法

 const promise = new Promise((resolve, reject) => {
            if (/* 异步操作成功 */) {
                resolve(value);//成功调用
            } else {
                reject(error);//失败调用
            }
     }
       promise.then(res => {
                console.log(res)
            }, err => {
                console.log(err)
            });

复制代码

普通结构创建

var promise = new Promise(function(resolve, reject) {
   resolve('hello');
});
promise.then(value=>{
  console.log(value);
}).catch(error=>{
  console.log(error);
})
复制代码

2.Promise.resolve(value)快捷构造

静态方法 Promise.resolve(value) 可以认为是 new Promise() 方法的快捷方式。

Promise.resolve(1)
     .then((res) => {
          return 2
     })
     .catch((err) => {
          return 3
      })             
复制代码

3.延迟执行

 执行顺序:ok doen(1秒后出打印信息)
 function basicTimeOut(ms) {
            return new Promise((resolve, reject) => {
                console.log('ok')
                setTimeout(resolve, ms, 'doen')
            })
        }
        basicTimeOut(1000).then(res => {
            console.log(res)
        })
复制代码

4.Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的

解释:Promise 新建后就会立即执行, then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行

执行顺序:promise hi resove
function basic1() {
            let p = new Promise((resove, reject) => {
                console.log('promise')
                resove()
            })
            return p
        }
        basic1().then(() => {
            console.log("resove!")
        })
        console.log("hi!")
复制代码
执行顺序:1 2 4 3
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
复制代码

5.两个Promise p1的结果作为p2的参数

解释:两个Promise 但是p2的resolve方法将p1作为参数,这时p1的状态就会传递给p2,即一个异步操作的结果是返回另一个异步操作
p1的状态决定了p2的状态。
如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;
如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行

执行顺序:p1 p2 hahaha resuleerror
       p1 p1oooo p2 p2oooo hahaha resuleerror//调用resolve或reject并不会终结 Promise的参数函数的执行
   
const p1 = new Promise(function (resolve, reject) {
           console.log("p1")
           setTimeout(() => reject(new Error('fail')), 3000)
           console.log("p1 oooo")
       })

       const p2 = new Promise(function (resolve, reject) {
           console.log("p2")
           setTimeout(() => resolve(p1), 1000)
           console.log("p2 oooo")
       })

       p2.then(result => {
           console.log("resule", result)
       }).catch(error => {
           console.log("resuleerror", error)
       })
       console.log('hahahh')
    
复制代码

6.调用resolve或reject并不会终结 Promise 的参数函数的执行

解释:调用resolve或reject并不会终结 Promise 的参数函数的执行,并且会立即执行
这是因为resolved() Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务

执行顺序:2 1
      new Promise((resolve, reject) => {
          resolve(1);
          console.log(2);
      }).then(r => {
          console.log(r);
      });
复制代码

7.加上return 后面的就不会再执行了

解释:一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外

执行顺序:3
       new Promise((resolve, reject) => {
           return resolve(3);
           // 后面的语句不会执行
           console.log(4);
       }).then(r => {
           console.log(r);
       });
复制代码

8.js执行机制先执行同步,再执行

解释:第一轮事件循环,先执行宏任务,主script,new Promise立即执行,输出 3,执行p这个new Promise操作,输出 7,发现setTimeout,将回调函数放入下一轮任务队列(Event Quene),p的then,暂且命名为then1,放入微任务队列,且first也有then,命名为then2,放入微任务队列。执行console.log(4),输出 4,宏任务执行结束。
再执行微任务,执行then1,输出 1,执行then2,输出 3.
第一轮事件循环结束,开始执行第二轮。第二轮事件循环先执行宏任务里面的,也就是setTimeout的回调,输出 5.resolve(6)不会生效,因为p的Promise状态一旦改变就不会再变化了。

执行顺序:3,7,4,1,2,5 (resolve(6);无效,因为priomsie一经改变就不再变化)
 const first = () => (new Promise((resolve, reject) => {
           console.log(3);
           let p = new Promise((resolve, reject) => {
               console.log(7);
               setTimeout(() => {
                   console.log(5);
                   resolve(6);
               }, 0)
               resolve(1);
           });
           resolve(2);
           p.then((arg) => { console.log(arg)});
       }));
       first().then((arg) => { console.log(arg)});
 console.log(4);
复制代码

9. promise有3种状态

解释:1.promise 有 3 种状态: pending(进行中)fulfilled(已成功)rejected(已失败)
2.状态改变只能是 pending->fulfilled 或者 pending->rejected,状态一旦改变则不能再变。上面 promise2 并不是 promise1,而是返回的一个新的 Promise 实例。

执行顺序 :promise1 Promise {<pending>}
         promise2 Promise {<pending>}

         promise.html:142 Uncaught (in promise) Error: error!!!

         promise1 Promise {<fulfilled>: "success"}
         promise2 Promise {<rejected>: Error: error!!!
                  
  const promise1 = new Promise((resolve, reject) => {
               setTimeout(() => {
                   resolve('success')
               }, 1000)
           })
           const promise2 = promise1.then(() => {
               throw new Error('error!!!')
           })

           console.log('promise1', promise1)
           console.log('promise2', promise2)

           setTimeout(() => {
               console.log('promise1', promise1)
               console.log('promise2', promise2)
           }, 2000)
复制代码

10. 构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用,

解释:呼应代码二结论:promise 状态一旦改变则不能再变。

打印顺序:then:success1
     const promise = new Promise((resolve, reject) => {
               resolve('success1')
               reject('error')
               resolve('success2')
     })
     promise.then((res) => { console.log('then: ', res)})
            .catch((err) => {  console.log('catch: ', err)})
    
       
打印顺序:catch:error
     const promise = new Promise((resolve, reject) => {
               reject('error')
               resolve('success2')
     })
     promise.then((res) => { console.log('then: ', res)})
            .catch((err) => {  console.log('catch: ', err)})
复制代码

5.Promise.prototype.then() :链式操作

Promise.prototype.then() then()方法定义在原型对象Promise.prototype上的

用法:promise.then(success,fail) //两个参数:成功做的,失败做的
作用:用于为 Promise 实例添加状态改变时的回调函数
采用链式写法:then方法返回的是一个新的promise实例(不是原来那个promise实例)s所以可以采用链式写法,then方法后面再调用另一个then方法。

1.基本用法

getJSON("/posts.json").then(function(json) {
 return json.post;
}).then(function(post) {
// ...
});
复制代码

2.采用链式的then

1.如果返回新的promise,那么下一级.then()会在新的promise状态改变之后执行
第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为resolved,就调用第一个回调函数,如果状态变为rejected,就调用第二个回调函数。

getJSON("/post/1.json").then(post=> {
 return getJSON(post.commentURL);
}).then(comments=> {
 // 对comments进行处理
 console.log("resolved: ", comments);
}, function (err){
 console.log("rejected: ", err);
});
复制代码

3.采用链式的then 后一个回调函数,就会等待该promise对象的状态发生变化,才会被调用

Promise.resolve(value) 能快速构建

打印顺序: ok  ok1  (ok1步骤出错因此,不会执行下面的then)
       Promise.resolve(100)
           .then(value => {
               console.log('ok')
               return value * 2;
           })
           .then(value => {
               console.log('ok1')
               throw new Error('A 函数出错');
           })
           .then(value => {
               console.log('ok2')
               console.log("1: " + value);
           })

Promise.resolve(value) 能快速构建
打印顺序: ok  ok1  ok3  1Error ok4 1unfinne
(ok1步骤出错因此,不会执行下面的then,但要执行catch)
       Promise.resolve(100)
           .then(value => {
               console.log('ok')
               return value * 2;
           })
           .then(value => {
               console.log('ok1')
               throw new Error('A 函数出错');
           })
           .then(value => {
               console.log('ok2')
               console.log("1: " + value);
           })
           .catch(value => {
               console.log('ok3')
               console.log("1: " + value);
           })
           .then(value => {
               console.log('ok4')
               console.log("1: " + value);
           })
复制代码

4.promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值

打印顺序: once 
        ok:100 105
        ok2: 100 101
        ok1:105 110
 const promise = new Promise((resolve, reject) => {
               setTimeout(() => {
                   console.log('once')
                   resolve(100)
               }, 1000)
           })
           promise.then((res) => {
               console.log('ok', res, res + 5)
               return res + 5;
           }).then(res => {
               console.log('ok1', res, res + 5)
           })

           promise.then((res) => {
               console.log('ok2', res, res + 1)
           })
复制代码

5.then 或者 .catch 中 return 一个 error 对象并不会抛出错误

1.then , .catch 中 return 一个 error 对象并不会抛出错误,不会被后续的 .catch 捕获
2.return Promise.reject(new Error(‘error!!!’))或者 throw new Error(‘error!!!’) 才会抛出错误
3.因为返回任意一个非 promise 的值都会被包裹成 promise 对象
return new Error(‘error!!!’) 等价于 return Promise.resolve(new Error(‘error!!!’))。

打印顺序: 打印顺序:then1:  Error: error!!!
  Promise.resolve()
              .then(() => {
                  return new Error('error!!!')
              })
              .then((res) => {
                  console.log('then1: ', res)
              })
              .catch((err) => {
                  console.log('catch: ', err)
              })
复制代码

6.Promise.prototype.catch()

Promise.prototype.catch()
用法:Prom ise.catch()
作用:用于指定发生错误时的回调函数
then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获
例子:Promise.catch(err=>{console.log(err)});
联合使用:Promise.then().catch()

6.1.Promise 状态已经变成resolved,再抛出错误是无效的
Promise 的状态一旦改变,就永久保持该状态,不会再变了

打印顺序:ok
const promise = new Promise(function(resolve, reject) {
 resolve('ok');
 throw new Error('test');
});

promise
 .then(function(value) { console.log(value) })
 .catch(function(error) { console.log(error) });
复制代码

6.2.Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获

打印顺序:then:  then1:  catch:
Promise.resolve()
     .then(() => {
          console.log('then: ')
      })
     .then((res) => {
          console.log('then1: ', res)
          reject(new Error('test'));
      })
     .then((res) => {
          console.log('then2: ', res)
      })
     .catch((err) => {
          console.log('catch: ', err)
     })
复制代码

6.3.then的第二个参数也是异常抛出但不建议使用

// bad
promise.then(function(data) {
   // success
 }, function(err) {
   // error
 });
// good
promise.then(function(data) {
   // success
 })
 .catch(function(err) {
   // error
 });
复制代码

7.Promise.resolve()

作用:快速转成promise对象
例子:Promise.resolve(‘foo’)
// 等价于
new Promise(resolve => {
resolve();
})

8.all()

用法:Promise.all([p1,p2,p3])
作用:方法用于将多个 Promise对象包装成一个新的数组Promise对象
注意:必须确保,所有的Promise对象都是resolve成功状态
1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
两个请求p1,p2同时发出,用all同时发,
最后成功结果成一个res中,用解构赋值再分解出来

下面的执行顺序:1,2 3:hello1,hello  
                    hello1 hello undefined
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
const p2 = new Promise((resolve, reject) => {
resolve('hello1');
})
Promise.all([p2, p1])
.then(result => {
let [res1,res2,res3]=res;
})
.catch(e => console.log(e));
复制代码

9.实例
9.1.异步加载图片

function loadImageAsync(url) {
 return new Promise((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;
 });
}
或者
const preloadImage = function (path) {
 return new Promise((resolve, reject)=>{
   const image = new Image();
   image.onload  = resolve;
   image.onerror = reject;
   image.src = path;
});
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享