夜话Promise(上)

作者: Angeladaddy | 来源:发表于2018-01-26 00:18 被阅读31次

1. 什么是Promise?为什么需要它?

从最简单的例子开始- app.js

Code Example 1-最简单的promise:

let promiseToCleanTheRoom = new Promise(function(resolve,reject){

    let isClean = true;

    if(isClean){
        resolve();
    }
    else {
        reject();
    }
})

promiseToCleanTheRoom.then(function(){
    console.log('Room is clean');
}).catch(function(){
    console.log('Room is not clean');
})

isClean=true | false时,输出:Room is clean | Room is not clean
如果不用Promise,应该怎么写?

let promiseToCleanTheRoom = function (successCallback, errorCallback) {

    let isClean = true;

    if (isClean) {
        successCallback();
    }
    else {
        errorCallback();
    }
}

promiseToCleanTheRoom(function(){
    console.log('Room is clean');
},function(){
    console.log('Room is not clean');
})

可以看到,我们不得不把方法当做参数进行传递。
在这个例子中,使用和不使用Promise的区别不大,但如果遇到下面这种情况,估计就抓狂了:

setTimeout(function() {
    setTimeout(function() {
        setTimeout(function() {
           // do something...
        }, 1);
    }, 1)
}, 1)

ok, 欢迎来到javascript 回调地狱,我猜你是回不去了


javascript callback hell

为加深印象,再看一段代码(promise官网例子):

function readJSONSync(filename) {
  return JSON.parse(fs.readFileSync(filename, 'utf8'));
}

代码乍一看很正常,但如果这个文件非常大,或者假设硬盘非常非常慢,一秒只能读1kb呢??在javascript的单线程世界里,我们怕是要一直等下去了...
我们知道,这种情况叫做同步编程,方法名里的Sync也证明了这一点。其它语言都有很好的多线程支持,比如c#的Thread。js处理多线程用的是方法回调:

function readJSON(filename, callback){
  fs.readFile(filename, 'utf8', function (err, res){
    if (err) return callback(err);
    callback(null, JSON.parse(res));//此处有隐患
  });
}

把callback传进去,就这么简单直接,有没有很眼熟?是的,express就是这个写法:

app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

这里的next就是callback,前面的function也是。知道为什么express作者要开发koa了吧。为了躲开callback hell。
回到上面读json文件那个例子中我标出此处有隐患的地方,如果这个地方json文件格式不合适,读取发生错误呢?(-ps:这种情况真的很多见),我们需要try catch错误;那么代码又变成下面这个样子:

function readJSON(filename, callback){
  fs.readFile(filename, 'utf8', function (err, res){
    if (err) return callback(err);
    try {
      res = JSON.parse(res);
    } catch (ex) {
      return callback(ex);
    }
    callback(null, res);
  });
}

这样,callback函数就需要同时负责处理异常和正常数据。知道express的异常处理函数,第一个参数为什么必须是err了吧?

function errorHandler(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}

2. 怎么使用Promise?

根据官方文档,Promise有以下3种状态:

  • pending:初始状态
  • fulfilled:成功状态
  • rejected:失败状态

要使用promise我们首先得有一个promise,我们可以非常轻松的定义它:

function readFile(filename, enc){
  return new Promise(function (fulfill, reject){
    fs.readFile(filename, enc, function (err, res){
      if (err) reject(err);
      else fulfill(res);
    });
  });
}

可以看到,我们把生成promise对象的工作都交给了构造函数,同时传入fulfill, reject两个参数,它们将在合适的时候被调用。注意:我们没有传入callback 方法。
同时也注意到,readFile还是使用了callback啊?是的,要用Promise,就得所有的地方都用 Promise。对于 Node 的原生 API,需要进行二次封装。

使用promise很简单:

readFile('file.txt', 'utf8').then(function (res) {
    console.log(res);
}).catch(function (err) { 
    console.log('errors:' + err);
})

小结:

  • Promise 是对方法进行的一种封装,避免在js异步编程中将方法当做参数直接传递,从而有效避免了callback hell.

下次再说promise下集

相关文章

  • 夜话Promise(上)

    1. 什么是Promise?为什么需要它? 从最简单的例子开始- app.js Code Example 1-最简...

  • Promise

    Promise迷你书 Promise在规范上规定 Promise只能使用异步调用方式 。 Promise.reso...

  • ES6-Promise对象 (下)

    ES6-Promise对象 (上) 1.Promise对象方法 (1)Promise.all(iterable);...

  • js 异步系列(3) -promise中

    上一节promise上已经根据promise/A+规范写出了基本的Promise类的基本框架。 那么在promis...

  • 古玩夜话目录

    【玄幻古风】古玩夜话(1)序言 【玄幻古风】古玩夜话(2)并蒂莲(上) 【玄幻古风】古玩夜话(3)并蒂莲(下) 【...

  • async/await

    async实际是对promise上的扩展,使用了promise并不和promise冲突 - then 将callb...

  • Promise.finally、Promise.all、Prom

    Promise原型对象上的方法 Promise构造函数中定义的方法 1. Promise.prototype.fi...

  • Promise笔记

    Promise学习(上): 资料: JavaScript Promise迷你书 原著:azu / 翻译:liubi...

  • 简单记录一下Promise的使用方法

    Promise 作用 Promise意在让异步代码变得干净和直观,让异步代码变得井然有序。 Promise在设计上...

  • Promise

    1. Promise介绍 1.1 定义 Promise 是异步编程的一种解决方案: 从语法上讲,promise是一...

网友评论

    本文标题:夜话Promise(上)

    本文链接:https://www.haomeiwen.com/subject/jdgbaxtx.html