promise的使用与实现

promise概念:

Promise对象是一个构造函数,用来生成promise实例。

Promise代表一个异步操作,有三种状态pending,resolved(异步操作成功由pending转为resolved)rejected(异步操作失败由pending转为rejected),一旦变成 resolve 或 reject两种状态后不会再更改。

resolve函数在异步操作成功后调用,将pending状态变为resolve,并将它的参数传递给回调函数;reject函数在异步操作失败时调用,将pending状态改为rejected,并将参数传递给回调函数。

注意:promise状态只能由pending=>fulfilled/rejected,一旦修改就不能再变。

Promise构造函数的原型有一个then方法,他接受两个函数作为参数,分别为resolved状态和rejected状态的回调函数,而这两个回调函数接受的参数分别是Promise实例中resolve和reject函数中的参数。

链式调用:

Promise实例在生成后会立即执行,而then方法只有在所有同步任务执行完成之后才会执行:

const promise=new Promise((resolve,reject)=>{
  console.log('async task begins!')
  setTimeout(()=>{
    resolve('done,pending->resolved!')
  },1000)
})
promise.then(value=>{
  console.log(value)
})
console.log('1.please wait');
console.log('2.please wait');
console.log('3.please wait');

打印结果:

// async task begins!

// 1.please wait

// 2.please wait

// 3.please wait

// done, pending -> resolved!

解析:

Promise实例生成后立即执行,首先输出‘async task begins!’

遇到1秒后执行的setTimeout,无需等待,向下执行

then方法指定的回调函数要在所有同步任务执行完毕之后才执行,所以先输出3个‘please wait’

最后输出‘done,pending->resolved!’(then打印的是resolve返回的值)

链式调用then方法:(then返回一个新的Promise实例):

.then 方法会返回一个新的 Promise 实例,可以分两种情况来看:

  1. 指定返回值是新的 Promise 对象,如return new Promise(...),这种情况没啥好说的,由于返回的是 Promise,后面显然可以继续调用then方法。
  2. 返回值不是Promise, 如:return 1 这种情况还是会返回一个 Promise,并且这个Promise 立即执行回调 resolve(1)。所以仍然可以链式调用then方法。(注:如果没有指定return语句,相当于返回了undefined)

示例:两秒钟打一次招呼

function sayHi(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(name);
    }, 2000)
  })
}

sayHi('张三')
  .then(name => {
    console.log(`你好, ${name}`);
    return sayHi('李四');    // 最终 resolved 函数中的参数将作为值传递给下一个then
  })
  // name 是上一个then传递出来的参数
  .then(name => {                
    console.log(`你好, ${name}`);
    return sayHi('王二麻子');
  })
  .then(name => {
    console.log(`你好, ${name}`);
  })

// 你好, 张三

// 你好, 李四

// 你好, 王二麻子

Promise可以在有若干个异步任务,需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。

串行执行任务:

// 0.5秒后返回input*input的计算结果:
function multiply(input) {
    return new Promise(function (resolve, reject) {
        log('calculating ' + input + ' x ' + input + '...');
        setTimeout(resolve, 500, input * input);
    });
}

// 0.5秒后返回input+input的计算结果:
function add(input) {
    return new Promise(function (resolve, reject) {
        log('calculating ' + input + ' + ' + input + '...');
        setTimeout(resolve, 500, input + input);
    });
}

var p = new Promise(function (resolve, reject) {
    log('start new Promise...');
    resolve(123);
});

p.then(multiply)
 .then(add)
 .then(multiply)
 .then(add)
 .then(function (result) {
    log('Got value: ' + result);
});

并行执行任务:

试想一个页面聊天系统,我们需要从两个不同的URL分别获得用户的个人信息和好友列表,这两个任务是可以并行执行的,用Promise.all()实现如下:

var p1=new Promise(function(resolve,reject){
  setTimeout(resolve,500,'P1');
})
var p2=new Promise(function(resolve,reject){
  setTimeout(resolve,600,'P2');
})
//同时执行p1和p2,并在他们都完成后执行then:
Promise.all([p1,p2]).then(function(results){
  console.log(result);//['P1','P2']
})

有些时候,多个异步任务是为了容错。比如,同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现:

var p1=new Promise(function(resolve,reject){
  setTimeout(resolve,500,'P1');
})
var p2=new Promise(function(resolve,reject){
  setTimeout(resolve,600,'P2');
})
Promise.race([p1,p2]).then(function(results){
  console.log(result);//['P1'']
})

由于p1执行较快,Promise的then()将获得结果'P1'。p2仍在继续执行,但执行结果将被丢弃。

promise的实现:

实现一个简单的Promise:

function Promise(fn){
  var status='pending';
  function successNotify(){
    status='fulfilled';//状态变为fulfilled
    toDoThen.apply(undefined,arguments);//执行回调
  }
  function failNotify(){
    status="rejected";//状态变为rejected
    toDoThen.apply(undefined,arguments);
  }
  function toDoThen(){
    setTimeout(()=>{//保证回调是异步执行的
    if(status==='fulfilled'){
      for(let i=0;i<successArray.length;i++){
        successArray[i].apply(undefined,arguments);//执行then里面的回调函数
      }
    }else if(status==='rejected'){
      for(let i=0;i<failArray.length;i++){
        failArray[i].apply(undefined,arguments);//执行then里面的回调函数
      }
    }
  })
}
var successArray=[];
var failArray=[];
fn.call(undefined,successNotify,failNotify);
return{
  then:function(successFn,failFn){
    successArray.push(successFn);
    failArray.push(failFn);
    return undefined;//此处应该返回一个Promise
  }
 }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值