JavaScript Promise的用法

2018-05-04  本文已影响0人  楼主楼主

Promise是JavaScript ES6中的一个新特性,用于异步处理。在没有Promise之前,做异步调用通常使用callback函数的方式:

function callback(data){
  console.log(data);
}
function foo(data,callback){
  //模拟延时返回
  setTimeout(callback,2000,data);
}
foo('hello!',callback);

执行代码 一段时间后 控制台打印hello!

通常我们对异步调用的使用会更加复杂,比如异步调用有可能执行成功或者失败,可能存在着嵌套,多个异步调用全部完成后再执行某些代码等等。用上面的方式,这些需求也是可以满足的,但是为了利于代码的易读、复用、标准化等等需求,ES6提供了Promise来完成这些任务。

一个最简单的Promise例子:生成一个随机数,如果大于0.5则成功,否则失败:

// 当随机数大于0.5则成功,否则失败
function foo(resolve, reject){
  var time = Math.random();
  setTimeout(function(){
    if(time<0.5){
      reject(time);
    }else{
      resolve(time);
    }
  },time*1000);
}
new Promise(foo)
  .then(result=>console.log('成功'+result))
  .catch(result=>console.log('失败'+result))

可见Promise把执行过程,处理结果,错误处理都分开了。


当有嵌套执行异步操作,我们需要任何任务失败则不再继续,并执行错误处理函数,Promise也可以让整个流程变得简洁。下面是一个Promise嵌套执行异步操作的例子:

// 定义被除数对象
function Dividend(value){
  var that = this;
  this.value = value;
  this.divided = function(divisor){
    console.log('计算 '+that.value+'除以'+divisor+'...')
    return divide(that.value,divisor);
  }
}

function divide(num,num1){
  return new Promise(function(resolve,reject){
    if(typeof(num) === 'number' && typeof(num1) === 'number'&& num1!==0){
      //通过resolve返回一个Dividend对象
      setTimeout(resolve, 500,new Dividend(num/num1));
    }else{
      setTimeout(reject, 500, '参数不是数字或者除数为0');
    }
  });
}

运行:

// 正确的运算
divide(100,2)
  .then(dividend=>dividend.divided(2))
  .then(dividend=>dividend.divided(2))
  .then(dividend=>dividend.divided(3))
  .then(dividend=>console.log("结果:"+dividend.value))
  .catch(reason=>console.log("错误:"+reason));
// 错误的运算
divide(100,2)
  .then(dividend=>dividend.divided(2))
  .then(dividend=>dividend.divided(0))
  .then(dividend=>dividend.divided(3))
  .then(dividend=>console.log("结果:"+dividend.value))
  .catch(reason=>console.log("错误:"+reason));

结果:

// 正确的运算
计算 50除以2...
计算 25除以2...
计算 12.5除以3...
结果:4.166666666666667
// 错误的运算
计算 50除以2...
计算 25除以0...
错误:参数不是数字或者除数为0

除了串联执行若干异步任务外,Promise还可以并联执行异步任务。
并联执行的逻辑分为两种

  1. 当所有Promise执行完毕后执行任务
  2. 当任意一个Promise执行完毕后执行任务
// 当所有Promise执行完毕后执行任务
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) {
    // 获得一个Array: ['P1', 'P2'],结果的顺序和all函数中Promise的顺序一致
    console.log(results); });

//当任意一个Promise执行完毕后执行任务
var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
// 由于p1执行较快,Promise的then()将获得结果'P1'。p2仍在继续执行,但执行结果将被丢弃。
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});
上一篇下一篇

猜你喜欢

热点阅读