Promise异步编程,一篇带你解决

Promise基本介绍

什么是Promise?
所谓Promise,简单说就是一个容器,里面保存着通常是一个异步操作的结果。
什么是异步操作
js语言是单线程机制。单线程就是按次序执行,执行完一个任务再执行下一个。但是不影响异步还是同步 异步就是从主线程发射子线程完成任务 前一个任务结束后执行回调函数 后一个任务不等前一个任务执行 所以程序执行顺序和任务顺序排列的顺序是不一致的 所以称为异步任务

回调函数

一个函数(A)作为实参传入到另一个函数(B)当中 并且函数B在内部调用了 则称为回调函数

setTimeout(()=>{
  console.log("hello");
},1000)
console.log("666")

此时作为函数A console.log(“hello”);传入到定时器B中 称为回调函数
此时setTimeout会在子线程等待一秒 然后执行 但是它不会堵塞主线程
什么是回调地狱

  $.ajax({
        url: '我是第一个请求',
        type: 'get',
        success(res) {
            // 现在发送第二个请求
            $.ajax({
                url: '我是第二个请求',
                type: 'post',
                data: { a: res.a, b: res.b },
                success(res1) {
                    // 进行第三个请求
                    $.ajax({
                        url: '我是第三个请求',
                        type: 'post',
                        data: { a: res1.a, b: res1.b },
                        success(res2) {
                            console.log(res2)
                        }
                    })
                }
            })
        }
    })

对于以上代码 是一层一层向下嵌套的 不便于维护 且如果中间有些地方出错之后就会导致后面的无法进行
所以为了解决回调地狱的问题 Promise就出场了

Promise解决回调地狱的原理

在这里插入图片描述

Promise特点

Promise对象其实是构造函数 构造函数接受了function(resolve,rejected)作为参数 此时该函数就是Promise构造函数的回调函数 生成Promise实例resolve和reject
1 promise对象有三个状态 pending(进行中) fulfilled(已成功) rejected(已失败) 只有异步操作的结果可以改变promise的状态
2 一旦状态改变 从pending变到fulfilled pending变成rejected 则状态就凝固了
promise对象其实是构造函数 构造函数接受了function(resolve,rejected)作为参数 此时该函数就是promise构造函数的回调函数 生成promise实例resolve和rejected
另外
1promise在创建实例就会执行
● new Promise时传入的函数是同步执行的。在这个函数内部调用resolve或reject只是告诉Promise对象任务已经完成,但不会立即执行then方法绑定的回调。

     let p=new Promise(function(resolve,reject){
         console.log("6");
       resolve();
     })
     p.then(function(){
         console.log("9");
     })
     console.log("2");

因为立即执行 所以输出结果为6 9 2
调用reslove和rejecte并不会影响Promise函数的执行

new Promise((resolve, reject) => {
  resolve(1);
//    return  resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});

正常输出结果为 2 1
加上return resolve(1)后,Promise对象会立刻resolved,then回调会同步执行 所以此时2不会输出 而是直接执行回调函数
resolve函数目的是将promise的状态变为成功 在异步操作成功时候将参数传递出去 reject函数是将promise状态变成失败 在失败时候调用

Promise常用方法

then()和catch()

 new Promise(function(resolve,reject){
     //resolve(1);
     reject(1)
    })
     .then(function(res){
        console.log("成功",res);
    },function(err){
         console.log("失败",err);
     })
     new Promise((resolve,reject)=>{
         resolve(1)
     }).then(()=>{
         throw new Error;
     }).catch((err)=>{
         console.log(err);
    }) 

then方法有两个参数 一个当Promise对象成功时候作为回调函数调用 一个作为Promise对象失败时候调用
而catch相当于then方法的特例 只在失败时候调用 因为Promise对象失败具有冒泡的性质 所以会被最外层的catch捕获到错误

finally()

finally()方法用于指定不管Promise 对象最后的状态 如何,都会执行的操作。
finally 方法的回调函数不接受任何参数,所以finally方法里面的操作和promise 返回的状态无关,不依赖于promise的执行结果

 server.listen(port)
  .then(function () {
    // ...
  })
  .finally(server.stop);   

all()

romise.all() 方法用于将多个Promise 实例,包装成一个新的实例
接受一个数组作为参数 有以下几种情况
1 数组里面的promise实例都是fulfilled,新的实例状态才是fulfilled
2 实例对象只要有一个是rejected,p的状态就是rejected

const p1=new Promise((resolve,reject)=>{
    resolve("hello")
})                
.then(result=>result)
.catch(e=>e)
const p2=new Promise((resolve,reject)=>{
    throw new Error("报错了")
})
.then(result=>result)
.catch(e=>e)
Promise.all([p1,p2])
.then(result=>console.log(result))
.catch(e=>console.log(e))    

race()

因为Race有赛跑的意思 Promise.race方法用于处理多个Promise对象,只要有一个Promise对象执行成功或失败,race方法返回Promise对象就会兑现。

let fun1=new Promise((reslove,reject)=>{
    setTimeout(()=>{
        let data1='哈哈'
        reslove(data1);
    },400)
})     
let fun2=new Promise((reslove,reject)=>{
    setTimeout(()=>{
        let data2='哈哈哈'
        reslove(data2);
    },500)
})              
Promise.race([fun1,fun2])
.then((res)=>{
    console.log(res);
})
.catch((err)=>{
    console.log(err);
})   

reslove()

reslove()可以使其传递的参数变为Promise对象
参数有一下几种情况
1 Promise.reslove接受的参数是有then方法的 转成Promise对象之后直接调用对象里面的.then方法
2 参数是个Promise对象 不做任何改动
3参数不是对象 会返回一个新的Priomise对象 且状态是resloved
4没有参数 直接返回一个resloved的Promise对象

let thentable={
    then:function(reslove,reject){
        reslove(42)
    }
}
let p1=Promise.resolve(thentable);
p1.then(function(value){
    console.log(value);
})
const p = Promise.resolve('Hello');
p.then(function (s) {
  console.log(s)
});
const p2 = Promise.resolve();

p.then(function () {
  // ...
});   

Promise应用

封装ajax

    function sendAjaxRequest(url, method, params) {
        return new Promise(function (resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open(method, url);
            //封装请求的metho和地址
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function () {
            //判断返回码的状态
                if (xhr.readyState === XMLHttpRequest.DONE) {
                    if (xhr.status === 200) {
                        resolve(xhr.responseText);
                    } else {
                        reject(new Error(xhr.statusText));
                    }
                }
            };
            //处理发送请求失败
            xhr.onerror = function () {
                reject(new Error('ajax发送请求失败'));
            };

            if (method === 'POST') {
                xhr.send(JSON.stringify(params));
            } else {
                xhr.send();
            }
        });
    }

    // 使用示例
    sendAjaxRequest('http://localhost:5000/get/get', 'GET')
        .then(function (res) {
            console.log(res);
        })
        .then(function (res) {
            let sendData = { name: 'John', age: 25 };
            return sendAjaxRequest(`http://localhost:5000/get/sendReq?sendData=${sendData}`, 'GET');
        })
        .then(function (res) {
            console.log(res);
        })
        .catch(function (err) {
            console.log(err);
        });

封装axios

function sendAjaxRequest(url, method, params) {
  return new Promise(function(resolve, reject) {
    axios({
      method: method,
      url: url,
      data: params
    })
      .then(function(response) {
        resolve(response.data);
      })
      .catch(function(error) {
        reject(error);
      });
  });
}

// 使用示例
sendAjaxRequest('http://localhost:5000/get/get', 'GET')
  .then(function(res) {
    console.log(res);
  })
  .then(function() {
    let sendData = { name: 'John', age: 25 };
    return sendAjaxRequest("http://localhost:5000/get/sendReqPOST", 'POST', sendData);
  })
  .then(function(res) {
    console.log(res);
  })
  .catch(function(err) {
    console.log(err);
  });

判断图片状态

  const preloadImage = function (path) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = path;
  });
};

总结

Promise可以解决回调地狱 在交互中采用异步操作可以避免堵塞线程 对错误进行捕获 便于维护
下周主要还是写项目进行交互 然后就是可以整理一下原生js写的播放器 写的有点乱其实

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值