Promise

大纲

  • promise 的历史与规范
    • 流程控制的演进过程
    • 初识Promise
    • Promise的三种状态
    • Promise 流程控制
  • promise API
    • then 与 catch
    • then VS catch
    • Promise.resolve
    • Promise.reject
    • Promise.all
    • Promise.race

大纲

  • 非标准 API
    • done 与 finally
    • Promise.denodeify / nodeify
  • 不同实现的对比
    • jQuery的实现
    • when的实现
    • ES6的实现
  • promise 的最佳实践

js流程控制的演进过程

Callback → Async

Promise

Co(Generator/yield+Promise)

Async/await

  1. 回调地狱
  2. 并发难

初识Promise

new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('成功');
  }, 3000);
});
  • 必须严格遵守固定、统一的编程方式来编写代码

Promise的三种状态

  • pending
  • fulfilled
  • rejected

状态转换成Fulfilled或Rejected之后,不在发生变化

Promise 流程控制

function p1(count) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve(count);
    }, 3000);
  })
}

function p2(count) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve(count + 1);
    }, 1000);
  });
}

p1(1).then(p2).then(function (data) {
  console.log(data, Date.now() - time);
}).catch(function () {
  // 失败时调用的函数
});
var time = Date.now();
  • 永远是异步
  • error不会抛出到外部

promise API

then 与 catch

new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('成功');
  }, 3000);
}).then(function () {
  // 成功时调用的函数
}, function () {
  // 失败时调用的函数
}).catch(function () {
  // 失败时调用的函数
});
  • 返回一个新的promise(return的值会由 Promise.resolve(return的返回值) 进行处理)

then VS catch

Promise.resolve

new Promise(function(resolve){
  resolve('Berwin');
});

// 快捷方式
Promise.resolve('Berwin');
  • Promise.resolve(thenable) => newPromise [fulfilled]
  • Promise.resolve(promise) => promise
  • Promise.resolve(其他) => newPromise [fulfilled]

Promise.reject

new Promise(function(resolve,reject){
  reject(new Error('报错了~'));
});

// 快捷方式
Promise.reject(new Error('报错了~'));
  • Promise.reject(thenable) => newPromise [rejected]
  • Promise.reject(promise) => newPromise [rejected]
  • Promise.reject(其他) => newPromise [rejected]

Promise.all

var promise1 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('promise1');
  }, 3000);
});

var promise2 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('promise2');
  }, 1000);
});

var time = Date.now();
Promise.all([promise1, promise2]).then(function (results) {
  console.log(results);
  console.log(Date.now() - time);
});

Promise.race

var promise1 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('promise1');
  }, 3000);
});

var promise2 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve('promise2');
  }, 1000);
});

var time = Date.now();
Promise.race([promise1, promise2]).then(function (results) {
  console.log(results);
  console.log(Date.now() - time);
});

非标准 API

done

Promise.resolve('hello').then(function (value) {
  if (Math.random() < 0.5) {
    throw new Error('err!');
  } else {
    return value;
  }
}).done(function (data) {
  console.log(data);
}, function (err) {
  console.log(err);
});
  • done 不返回promise对象
  • done 中发生的异常会被直接抛给外面

finally

Promise.resolve('hello').then(function (value) {
  if (Math.random() < 0.5) {
    throw new Error('finally err!');
  } else {
    return value;
  }
}).then(function (value) {
  console.log(value); // => 'hello'
}, function (err) {
  console.log(err); // => finally err!
}).finally(function () {
  console.log('finish') // always called
});
  • finally 没有任何参数

Promise.denodeify / nodeify

// denodeify
var readFile = Promise.denodeify(require('fs').readFile);
readFile('denodeify.txt', 'utf8').then(JSON.parse);
// nodeify
var readFile = Promise.denodeify(require('fs').readFile);
function readJson(filename, callback) {
  return readFile(filename, 'utf8').then(JSON.parse).nodeify(callback);
}

不同实现的对比

  • ES6的实现
  • jQuery的实现
  • when的实现

最佳实践