zoukankan      html  css  js  c++  java
  • nodejs中的promise基本操作

    1.为什么要使用promise

    /*
    需求:异步的按顺序去读取1.txt、2.txt、3.txt文件的内容
    假设 1.txt内容为111 、2.txt内容为222、3.txt内容为333
    */
    var  fs = require('fs');、
     fs.readFile('./files/1.txt','utf8',function(err,data){
       if(err){
         throw err;
       }
       console.log(data);
     })
    
     fs.readFile('./files/1.txt','utf8',function(err,data){
       if(err){
         throw err;
       }
       console.log(data);
     })
    
     fs.readFile('./files/1.txt','utf8',function(err,data){
       if(err){
         throw err;
       }
       console.log(data);
     })
    /*
     结果:111 222 333。(好像满足需求啊)
    */
    
    /* 
    问题:上面的代码虽然正常按照顺序读取了文件,因为文件的内容都非常少,io读取耗时少,但当2.txt内容较多时候,2.txt的内容是最后输出的。因为他们都是异步操作,不知道谁先读取完。 这得取决于异步任务IO的耗时。
    */
    
    /*
    常规解决办法:
    在第一个异步任务读取成功之后再读取第二个异步任务,
    第二成功后,在读取第三个异步任务
    */
    //读取第一个异步任务
    fs.readFile('./files/1.txt','utf8',function(err,data){
      if(err){
        throw err;
      }
      console.log(data);
      //读取第二个异步任务
      fs.readFile('./files/2.txt','utf8',function(err,data){
        console.log(data);
        //读取第三个异步任务
        fs.readFile('./files/3.txt','utf8',function(err,data){
          console.log(data);
        })
      })
    })
    
    /* 
    结果: 111 222 333 (这必须按照顺序输出的,结果杠杆的)  
    */
    
    /*
    问题:
    以上按照顺序执行多个异步任务产生的问题:`回调地狱`问题(层层包裹进行回调,代码也不够优雅)
    */
    
    /* 
    解决办法:采用es6,提供的promise来解决上述产生的问题。
    */
    

    2.Promise基本使用

    promise介绍:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

    
    //简单说promise就是用来执行异步任务的,可以解决上面所说的回调地狱问题,
    //语法:new Promise(function(callback){})
    var  fs = require('fs');
    var promise = new Promise(function(resolve,reject){
      //这里就是写异步的代码,只要new  Promise操作,就会立刻执行这里的代码
      //两个参数 resolve 异步执行成功的回调函数,reject异步执行失败的回调函数
      fs.readFile('./files/1.txt', 'utf8', function (err, data) {
        if (err) {
          throw err;
        }
        console.log(data);
      })
    });
    //运行结果:111
    

    3.promise参数resolve和reject

    两个参数

    • resolve 异步执行成功的回调函数,
    • reject异步执行失败的回调函数
    
    var fs = require('fs');
    var promise = new Promise(function (resolve, reject) {
      //两个参数: resolve 成功的回调函数名  , reject失败的回调函数名
      fs.readFile('./files/111.txt', 'utf8', function (err, data) {
        if (err) {
          //说明失败了,要执行失败的回调函数
          reject(err);
        } else {
          //成功的逻辑
          resolve(data);
        }
        //等价于
        // err ? reject(err) : resolve(data);
      })
    });
    
    //new Promise返回的是一个promise对象,
    //这个对象有一个方法叫做then,在其原型对象上
    //通过这then方法可以指定成功和失败的回调函数
    //语法:promise.then(successCallback,errorCallback);
    promise.then(function (data) {
      //then第一个函数是成功的回调,参数是resolve(err)中的data
      console.log('成功:' + data); // 若成功,运行结果:成功:111
    }, function (err) {
      //then第二个函数是失败的回调函数,参数是reject(err)中的err错误对象
      console.log('失败:' + err);
    });
    

    4.解决回调地狱问题

    
    //封装一个异步读取文件的内容的函数
    //此函数返回对应异步任务的promise对象
    function getFileByPath(path) {
      return new Promise(function (resolve,reject) {
        fs.readFile(path, 'utf8', function (err, data) {
          if(err){
            reject(err);   //失败
          }else{
            resolve(data);    //成功
          }
        })
      });
    }
    
    //由于then通过getFileByPath返回的是一个promise对象,所以可以继续.then串联调用(链式调用)
    getFileByPath('./files/1.txt')
    .then(function(data){
      console.log("成功:"+data);
      return getFileByPath('./files/2.txt');
    },function(err){
      console.log("失败:"+err);
      return getFileByPath('./files/2.txt');
    }) 
    .then(function(data){ 
      console.log("成功:"+data);
      return getFileByPath('./files/3.txt');
    },function(err){
      console.log("失败:"+err);
      return getFileByPath('./files/3.txt');
    })
    .then(function(data){
      console.log("成功:"+data);
    },function(err){
      console.log("失败:"+err);
    });
    
    

    注意:上面一定会保证按照.then的顺序去执行异步的代码,
    如果某个异步任务有错误则会触发对应then的第二个错误的回调函数。即每个promise对象都有对应的错误回调,对其他的promise不影响。毕竟promise的英文翻译就是保证。

    5.catch的使用

    catch也是在Promise.prototype原型上定义的。

    image.png

    需求:如果多个promise任务,其中有一个失败了,则终止后面的所有的promise执行

    getFileByPath('./files/1.txt')
    .then(function(data){
      console.log("成功:"+data);
      return getFileByPath('./files/2.txt');
    }) //上面的then通过getFileByPath返回的是一个promise对象,所以可以继续.then串联调用(链式调用)
    .then(function(data){ 
      console.log("成功:"+data);
      return getFileByPath('./files/3.txt');
    })
    .then(function(data){
      console.log("成功:"+data);
    })
    .catch(function(err){   
      // catch作用: 上面所有的promise如果其中一个有错误,
      //则终止下面所有的promise执行,且直接进入到catch中获取对应promise的异常错误信息
      console.log('catch:'+err);
    })
    
    

    注意:如果在then中定义了错误回调则不会进入到上面的catch中,这是因为promise对象指定了对应的错误处理回调。

    6 then-catch-finally

    
    var fs = require('fs');
    var promise = new Promise(function (resolve, reject) {
      //两个参数: resolve 成功的回调函数名  , reject失败的回调函数名
      fs.readFile('./files/11.txt', 'utf8', function (err, data) {
        if (err) {
          //说明失败了,要执行失败的回调函数
          reject(err);
        } else {
          //成功的逻辑
          resolve(data);
        }
      })
    });
    
    //new Promise返回的是一个promise对象,
    //这个对象有一个方法叫做then,在其原型对象上
    //通过这then方法可以指定成功和失败的回调函数
    //语法:promise.then(successCallback,errorCallback);
    promise.then(function (data) {
      //then第一个函数是成功的回调,参数是resolve(err)中的data
      console.log('成功:' + data); // 若成功,运行结果:成功:111
    }).catch(function(err){
      //then第二参数错误回调换成这里catch也行,两者选其一
      console.log('err');
    }).finally(function(){
      //无论失败成功都会执行
      console.log('完成');
    })
    
    

    7. Promise.all静态方法的使用

    参照:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise#%E6%96%B9%E6%B3%95
    需求:把所有的promise执行成功的结果保存在一个数组中。。

    var promise1 = getFileByPath('./files/1.txt');
    var promise2 = getFileByPath('./files/2.txt');
    var promise3 = getFileByPath('./files/3.txt');
    
    //执行多个异步任务,
    Promise.all([promise3,promise1,promise2]).then(function(data){
      console.log(data); 
    },function(err){
      console.log('错误了:'+err);
    })
    //Promise.all尤其是在一个页面上发起多个ajax请求的时候,如果要同时保证他们成功,则使用Promise.all是最合适不过的了。其中一个失败则也可以在then的第二个回调做失败的逻辑。
    
    

    若都成功,运行结果:['333','111','22']

    注意:Promise.all的成功结果是返回一个数组,且数组中数据的结果顺序与Promise.all数组的传参顺序是一样的。

  • 相关阅读:
    Spring 事务回滚机制详解
    【Azure 媒体服务】在Azure Media Service门户中使用HLS模式传输视频流,播放视频步骤
    【Azure 媒体服务】记录一个简单的媒体视频上传到Media Service无法播放问题
    【Azure 媒体服务】Azure Media Service Explorer 5.4.3.0 不能连接Media Service, 错误消息提示 BadRequest 和 Forbidden
    【Azure 应用服务】VS2019发布应用到正在运行的App Service时失败问题的解决
    【Azure 应用服务】[App Service For Linux(Function) ] Python ModuleNotFoundError: No module named 'MySQLdb'
    【Azure 应用服务】App Service For Container 配置Nginx,设置/home/site/wwwroot/目录为启动目录,并配置反向代理
    【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题
    【Azure 应用服务】如何定期自动重启 Azure App Service Plan(应用服务计划)
    【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
  • 原文地址:https://www.cnblogs.com/wjlbk/p/12633341.html
Copyright © 2011-2022 走看看