第十五章:promise-灵析社区

懒人学前端

一、promise 相关概念

回调方法:就是将一个方法 func2 作为参数传入另一个方法 func1 中,当 func1 执行到某一步或者满足某种条件的时候才执行传入的参数 func2

Promise 是 ES6 引入的异步编程的新解决方案。

Promise 对象三种状态:初始化、成功、失败 pending-进行中、resolved-已完成、rejected-已失败

就好像,你跟你女朋友求婚,她跟你说她要考虑一下,明天才能给你答案,这就是承诺(promise)。同时,这也是一个等待的过程(pending),然后你就等,等到明天你女朋友给你答复,同意(resolved)或者拒绝(rejected),如果同意就准备结婚了,如果不同意就等下次再求婚,哈哈哈。

promise 是用来解决两个问题的:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise 可以支持多个并发的请求,获取并发请求中的数据
  • 这个 promise 可以解决异步的问题,本身不能说 promise 是异步的

二、promise 基本用法

这样构造 promise 实例,然后调用 .then.then.then 的编写代码方式,就是 promise。

let p = new Promise((resolve, reject) => {      //    调用了Promise构造函数
  // 做一些事情
  // 然后在某些条件下resolve,或者reject
  if (/* 条件随便写^_^ */) {
    resolve()
  } else {
    reject()
  }
})

p.then(() => {                                 //    调用了promise实例的.then方法
    // 如果p的状态被resolve了,就进入这里
}, () => {
    // 如果p的状态被reject
})

三、声明一个 Promise 对象

new Promise((resolve, reject) => {     // 这两个方法主要是用来修改状态的
    console.log("开始求婚。")
    console.log("。。。。。")
    console.log("考虑一下。")
    setTimeout(() => {
        if (isHandsome || isRich) { // 当我们调用 resolve 函数的时候,Promise 的状态就变成 resolved
            resolve('我同意!')
        } else { // 当我们调用 reject 函数的时候,Promise 的状态就变成 reject
            reject("拒绝:我们八字不合")
        }
    }, 2000)
})
// 如果一个 promise 已经被兑现(resolved)或被拒绝(rejected),那么我们也可以说它处于已敲定(settled)状

四、Promise.prototype.then 方法

已成功 resolved 的回调和已失败 rejected 的回调

// 调用 Promise 对象的then方法,两个参数为函数
p.then(function(value){ // 成功
     console.log(value);
}, function(season){ // 失败
     console.log(season);
});

getNumber()

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

五、Promise.prototype.catch 方法

catch() 的作用是捕获 Promise 的错误

其实它和 then 的第二个参数一样,用来指定 reject 的回调,用法是这样:

在执行 resolve 的回调(也就是上面 then 中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死 js,而是会进到这个 catch 方法中。请看下面的代码:

promise.then(
    () => { console.log('this is success callback') }
).catch(
    (err) => { console.log(err) }
)

效果和写在 then 的第二个参数里面一样。不过它还有另外一个作用:在执行 resolve 的回调(也就是上面 then 中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死 js ,而是会进到这个 catch 方法中。请看下面的代码:

getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
    console.log(somedata);  //此处的somedata未定义
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

六、Promise.all() 方法

有了 all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据。

「谁跑的慢,以谁为准执行回调」

Promise 的 all 方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});

Promise.all 手撕代码题:

const myPromiseAll =(arr)=>{
     let result = [];
     return new Peomise ((resolve,reject)=>{
         for (let i=0;i<arr.length;i++){
             arr[i].then(data=>{
                 result[i] = data;
                 if(result.length === arr.length)//所有的都成功才执行成功的回调
                 {
                     resolve(result)
                   }//这里可以用计数器更好点
             },reject)//有一个失败则执行失败的回调
         }
     })
}

七、Promise.race() 方法

  • 「谁跑的快,以谁为准执行回调」
  • 1 秒后 runAsync1 已经执行完了,此时then里面的就执行了
  • 在 then 里面的回调开始执行时,runAsync2() 和 runAsync3() 并没有停止,仍旧再执行。
  • 于是再过 1 秒后,输出了他们结束的标志。
//请求某个图片资源
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
            resolve(img);
        }
        img.src = 'xxxxxx';
    });
    return p;
}

//延时函数,用于给请求计时
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('图片请求超时');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

Promise.race()手撕代码用法:

function promiseRace(promises) {
     if (!Array.isArray(promises)) {
         throw new Error("promises must be an array")
     }
    return new Promise(function (resolve, reject) {
         promises.forEach(p =>
             Promise.resolve(p).then(data => {
                 resolve(data)
                 }, err => {
                 reject(err)
             })
         )
     })
 }

八、Promise.any() 方法

any() 方法还接受一组 promise 作为参数,并将它们打包到新的 promise 对象中。只要一个参数实例处于成功状态,新的 promise 就处于成功状态。参数实例均处于拒绝状态。新承诺处于拒绝状态。

Promise.any(promises).then(
    (first) => {
    // Any of the promises was fulfilled.
    },(error) => {
    // All of the promises were rejected.
    }
);

注:同学们可以通过上面两道题目,举一反三,自己尝试写出手动实现 promise.any()

九、Promise.prototype.finally() 方法

finally 方法用于指定无论 Promise 对象的最终状态如何,都将执行 finally。Finally 不接受参数。Finally 独立于先前的执行状态,不依赖于先前的运行结果。

    const promise4 = new Promise((resolve, reject) => {
      console.log(x + 1);});
    promise4
      .then(() => {
        console.log("你好");}).catch((err) => {
        console.log(err);}).finally(() => {
        console.log("finally");});// finally


阅读量:2016

点赞量:0

收藏量:0