javaScript-promise总结

异步:每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

改变程序正常执行顺序,不阻塞线程。

具体可以参考我上一篇文章一道关于js宏任务、微任务面试题引发的思考

在浏览器端,耗时长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。

js中处理异步编程主要有以下几种:

1.回调函数
2.事件监听
3.发布/订阅
4.promise

今天来总结一下promise的概念和用法:

promise概念

promise是一个对象,是由 CommonJS 小组的成员在 Promises/A 规范中提出来的,它是用来处理异步操作的,能让我们在异步调用的时候不会像传统的回调函数那样繁琐,而是更美观更便于阅读,更合理更强大。而es6将其写进了语法标准,统一了用法。

promise用法

promise有三种状态
1.pending(进行中)
2.resolved(完成) ,fullfiled
3.rejected(失败)

promise两种过程
1.pending->resolved
2.pending->rejected

Promise对象有一个then方法,用来执行回调函数,该方法接受两个参数,一个是成功的resolved回调,另一个是失败的rejected回调,第二个失败的回调参数可选,并且.then()可以链式调用。

1.promise用new构建
new Promise(function(resolve,reject){});

var p = new Promise(function (resolve, reject) {
       console.log('执行操作1');
       var num = Math.floor(Math.random()*10);
           if(num>5){
               resolve(num);
        }else{
             reject(new Error());
        }
});
p.then(function (data) {//num大于5成功
      console.log(data);
      console.log('这是成功操作');
},function(data){//num小于等于5失败
       console.log(data);
       console.log('这是失败操作');
});
       

2.参数resolve是将Promise的状态置为fullfiled,reject的状态置为rejected。

3.常用的静态方法:all, race, reject,resolve等,原型对象上有有catch, then等方法。
静态方法调用直接Promise.all/Promise.race等;
原型对象的方法需要一个Promise的实例( new Promise )。

  1. .then()可以链式操作
    如下:依次弹出1,2,3
function count(n){
        return new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve(n);//成功
            },1000)
        })
    }
count(1).then(function(val){
      console.log(val);
      return count(2);
}).then(function(val){
      console.log(val);
      return count(3);
}).then(function(val){
      console.log(val);
})

  1. .catch()也是处理reject传递(处理发生错误)
    上面的代码可以改成
var p = new Promise(function (resolve, reject) {
      console.log('执行操作1');
      var num = Math.floor(Math.random()*10);
            if(num>5){
            resolve(num);
      }else{
            reject(new Error());
      }
});
p.then(function (data) {
      console.log(data);
      console.log('这是成功操作');
}).catch(function(data){//
      console.log(data);
      console.log('这是失败操作');
});

不管是.then()还是catch都会返回一个新建的promise对象

6.Promise.all 接受一个元素为promise对象的数组为参数,成功和失败的返回值是不同的,当所有对象返回resolve时,返回的是一个结果数组,而有一个返回reject时候则返回最先被reject失败状态的值。
Promise.all是等所有的异步资源都加载完毕之后,再执行代码,比如。
例如页面loading效果。
Promise.all主要解决的是多个异步模块的依赖问题,必须等大家都加载完毕之后,才执行,也就是等最慢的那个异步操作执行完了,再打印出结果 。

先看成功的代码

var p1 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve("p1");
            },1000)
        })
        var p2 = new Promise(function(resolve,reject){
             setTimeout(function(){
                resolve("p2");
            },3000)
        })
        Promise.all([p1,p2]).then(function(data){
            console.log(data);
            console.log("执行代码")
        })

打印结果为["p1","p2"] 执行代码
(这里面打印时间是按照3000)

下面返回reject的代码

var p1 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve("p1");
            },1000)
        })
        var p2 = new Promise(function(resolve,reject){
            setTimeout(function(){
                reject(new Error);
            },3000)
        })
        Promise.all([p1,p2]).then(function(data){
            console.log(data);
            console.log("执行代码")
        },function(data){
            console.log(data);
        })

打印结果为Error

6.Promise.race就是赛跑的意思,就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

var p3 = new Promise(function(resolve,reject){
            setTimeout(function(){
                resolve("p1");
            },1000)
})
var p4 = new Promise(function(resolve,reject){
          setTimeout(function(){
           reject(new Error);
    },2000)
})
Promise.race([p3,p4]).then(function(data){
       console.log(data);
       console.log("执行代码1")
}).catch(function(data){
       console.log(data);
       console.log("失败");
 })
//p1
//执行代码1
最后说一下async:

async 是“异步”的意思,而 await 是等待的意思。所以应该很好理解 async 用于申明一个 function是异步的(实际上是async function 对象),而 await 用于等待一个异步任务执行完成。

也就是说async告诉程序这个方法是存在异步操作,await是一个操作符,即 await 后面是一个表达式。

用法:

1.async 一个async函数,await只能用在这个函数里面。
2.async 函数返回的是一个 Promise 对象

async function testAsync() {
    return "hello async";
}
const result = testAsync();
console.log(result);

如果没有await,输出的是如下图


image.png

async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

所以要想获取数据,需要.then

Async().then(v => {
    console.log(v);    // 输出 hello async
});

3.await 表示在这里等待异步操作返回结果,再继续执行。
await 可以用于等待一个 async 函数的返回值,它不仅仅用于等 Promise 对象,它可以等任意表达式的结果,所以,await 后面实际是可以接普通函数调用或者直接量的。

这里借用阮一峰老师的解释:

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

function fn(){
     return new Promise(function(resolve,reject){
          setTimeout(function(){
               resolve("成功")
           },1000);
    })
}
async function A(){
        var v = await fn();
        console.log(v);
        console.log(123);
}
A();
//成功
//123

其实async结果和之前的 Promise 实现是一样的,如果有多个 Promise 组成的 then 链时,它会看起来更清晰,几乎跟同步代码一样。

await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。
async function myFunction() {
  try {
    await somethingThatReturnsAPromise();
  } catch (err) {
    console.log(err);
  }
}

// 另一种写法

async function myFunction() {
  await somethingThatReturnsAPromise().catch(function (err){
    console.log(err);
  });
}
具体可以查阅阮一峰老师的文章

async 函数的含义和用法

你可能感兴趣的:(javaScript-promise总结)