js—promise篇

174 阅读4分钟

1.怎么理解promise?

解决回掉地狱的问题,promise 对象用于表示一个异步操作的最终完成(或失败),及其结果值 blog.csdn.net/qq_42698326…

2.写出指定代码的输出内容?

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

1.同步的代码(最高) 3 7 4 2.微任务的异步代码(次高,then) 1 2 3.宏任务的异步代码 (最低,setTimeout) 5

注意:

  • 为什么没有6?一个Promise 里面只能调用一个resolve,因此先调用了1 就不会再调用6。
  • 多个Promise ,如何判断 resolve 对应于哪个Promise? 就近原则

3.promise实际应用

const openDoor= cb =>{
    setTimeout(cb,1000)
}

将上方封装成一个promise 函数

const promise = () =>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
        resolve();
        },1000)
    })
} 

链式调用

const openDoor= () => new Promise(resolve)=>{
    setTimeout(resolve,1000);
}
const putIn= () => new Promise(resolve)=>{
    setTimeout(resolve,1000*3);
}
const closeDoor= () => new Promise(resolve)=>{
    setTimeout(resolve,1000);
}
const done= () => new Promise(resolve)=>{
    console.timeEnd();
    console.log('done2);
    resolve();
}
openDoor().then(putIn).then(closeDoor).then(done);

4.自己实现一个promise

const Resolve = "resolved";
const Reject = "rejected";
const Pending = "pending";
const handlePromise=(result,newPromise,resolve,reject)=>{
  if(result===newPromise){ // 如果返回值 是一个newPromise 则没有意义
    throw new Error("can not return oneself");
  }
  if((typeof result === "object" && typeof result !==null) 
  || typeof result ==="function"){ // 判断返回的是不是一个promise
    let lock =false;
    try{
      const then = result.then;
    if(typeof then === "function"){
      then.call(result,(r)=>{ // 如果返回的是 newPromise.then 则执行
        if(lock){ // 如果promise是第3方的 需要执行 resolve 和reject 
          return;
        }
        handlePromise(r,newPromise,resolve,reject); 
        // 当promise 返回 {name:'123',then:123}
        lock=true;
      },(e)=>{
        if(lock){
          return;
        }
        reject(e);
        lock=true;
      })
    }else{
      resolve(result);
    }
    }catch(error){
      reject(error)
    }
    

  }else{
    resolve(result);
  }

};
class JJPromise{
  status = Pending;
  result = undefined;
  reason = undefined;
  onResolvedArr=[];
  onRejectedArr=[];
  constructor(excution){
    const resolve = (result) => {
      if(this.status === Pending){
        this.result = result;
        this.status = Resolve;
        this.onResolvedArr.map((fn)=>fn());
      }

    };
    const reject = (reason) => {
      if(this.status === Pending){
        this.reason = reason;
        this.status = Reject;
        this.onRejectedArr.map((fn)=>fn());
      }
    };
    try{
      excution(resolve,reject)
    }catch(error){
      reject(error)
    } 
  }
  then(onResolved,onRejected){
    onResolved = typeof onResolved ==="function"? onResolved:(data)=>data;
    onRejected = typeof onRejected ==="function"? onRejected:(err)=>{
    throw new Error(err)
    };
    const newPromise = new JJPromise((resolve,reject)=>{ //实现链式调用
      if(this.status === Resolve){
      setTimeout(()=>{ // 添加异步队列 解决 执行顺序问题
        try{
          const result = onResolved(this.result);
          handlePromise(result,newPromise,resolve,reject)
        }catch(error){
          reject(error)
        }
      },0)   
    }
    if(this.status === Reject){
      setTimeout(()=>{
        try{
          const result = onRejected(this.reason);
          handlePromise(result,newPromise,resolve,reject)
        }catch(error){
          reject(error)
        }
      },0)  
    }
    if(this.status === Pending){ 
    // 发布订阅模式 解决  promise 中 setTimeOut(()=>{resolve("1111")},1000); 执行问题
      this.onResolvedArr.push(()=>{
        try{
          const result = onResolved(this.result);
          handlePromise(result,newPromise,resolve,reject) //链式调用的第二个promise 执行,否则不执行
        }catch(error){
          reject(error)
        }
      });
      this.onRejectedArr.push(()=>{
        try{
          const result = onRejected(this.reason);
          handlePromise(result,newPromise,resolve,reject)
        }catch(error){
          reject(error)
        }
      });
    }
    })

    return newPromise;

}
  catch(onRejected){
    return this.then(undefined,onRejected)

  }
}

module.exports = JJPromise;


const test = new JJPromise((resolve,reject)=>{
  resolve("我们是最棒的");
})
test.then((res)=>{
  console.log(res);
}).then((res)=>
  console.log("1111")
);

console.log(123);

5.Promise.all()如何实现的

let p1=new Promise(resolve=>resolve('p1'));
let p2=new Promise(resolve=>resolve('p2'));	
let p3=Promise.reject('p3 promise');

      function promiseAll(promises){
       return new Promise ((resolve,reject)=>{
        let resultCount = 0;
        let results = new Array(promises.length);
        for(let i=0;i<promises.length;i++){
         promises[i].then(item=>{
          resultCount++;
          results[i]=item;
          if(resultCount==promises.length){
          return resolve(results);
          }
         },error=>{
          return reject(error)
         })
        } 
       })
      }

	promiseAll([p1,p2,p3]).then(result=>{
	   console.log('111',result)
	}).catch(error=>{
	   console.log(error)
	})

4.promise相关知识点

1.创造了一个Promise实例
const promise = new Promise(function(resolve, reject) {
  // ... some code
if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
2.Promise.prototype.then()

then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function (comments) {
  console.log("resolved: ", comments);
}, function (err){
  console.log("rejected: ", err);
});
3.Promise.prototype.catch()
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)。因此,建议总是使用catch()方法,而不使用then()方法的第二个参数。

4.Promise.prototype.finally()

方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

5.Promise.all()
const p = Promise.all([p1, p2, p3]);

只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数

6.Promise.race()
const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

7.Promise.allSettled()

Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。

8.Promise.any()

ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束。

mp.weixin.qq.com/s/6Jsz_mskT…