• Vue.js 之 Promise 对象(七)


    一、Promise 概念

    Promise 是一个构造函数,new Promise() 可以得到一个 Promise 实例对象,它是一个异步操作,可以用来执行一些异步操作(异步操作不能直接 return 接收执行结果,只能通过回调来接收)。

    回调函数

    • resolve():成功之后调用的回调函数
    • reject():执行失败调用的回调函数

    实例对象/方法

    Prototype 属性有一个 .then() 方法,它可以预先为 Promise 异步操作指定 成功 resolve() 和失败 reject() 的回调Promise 实例对象可直接调用 .then() 方法。

    注意:可以在浏览器调试界面打印输出 Promise 对象的内置方法,使用方法:console.dir(Promise)

    二、形式上的异步操作和具体的异步操作

    形式上的异步操作(只是形式上的,并没有其他任何异步操作):

    var promise = new Promise()		
    

    具体的异步操作:

    var promise = new Promise(function(){
      // function 内部就是具体的异步操作
    })
    

    三、快速上手

    创建一个 Promise 对象,用于读取文件内容,新建 read_file.js

    const fs = require('fs')
    
    // new 一个 Promise() 对象,内部异步操作:读写文件
    var promise = new Promise(function () {
        fs.readFile('./files/1.txt', 'utf-8', (err, resp) => {
            if (err) throw err
            // if (err) throw err      // 若读写文件有错,则 throw 掉,不执行这段
            console.log(resp)
        })
    })
    

    命令行执行:node read_file.js,运行 read_file.js 文件,发现这个 Promise 实例会被立即执行,这是因为 每当 new 一个 Promise 实例的时候,就会立即 执行这个 异步操作中的代码

    要想不立即执行,而是需要的时候再调用,可以将其封装到函数中:

    function readFile(file_path) {
        var promise = new Promise(function () {
            fs.readFile(file_path, 'utf-8', (err, resp) => {
                if (err) throw err
                // if (err) throw err      // 若读写文件有错,则 throw 掉,不执行这段
                console.log(resp)
            })
        })
        
    }
    
    readFile('./files/1.txt')
    

    四、通过 then 指定回调

    异步操作不能直接 return 获取执行结果,而是需要通过回调函数获取,Promise 中可以通过 .then() 来指定回调。

    const fs = require('fs')
    
    function getFile(file_path) {
        var promise = new Promise(function (resolve, reject) {
            fs.readFile(file_path, 'utf-8', (err, resp) => {
                if (err) return reject(err)     // 失败的回调
                
                // 成功的回调
                resolve(resp)
            })
        })
    
        return promise
    }
    
    var p = getFile('./files/1.txt')
    
    // 预先指定回调
    p.then(function(resp) {
        // 执行成功
        console.log('执行成功:', resp)
    }, function(err) {
        // 执行失败
        console.log('执行失败:', err)
    })
    

    这里将 promise 实例对象返回,再用一个变量 p 接收,通过 p 调用 then() 方法从而预先指定回调;读取文件这个异步操作不会立即执行,而是等 then() 指定了回调后才执行。

    也可以省略接收变量,直接调用 then()

    function getFile(file_path) {
        return new Promise(function (resolve, reject) {
            fs.readFile(file_path, 'utf-8', (err, resp) => {
                if (err) return reject(err)     // 失败的回调
                
                // 成功的回调
                resolve(resp)
            })
        })
    
    }
    
    getFile('./files/1.txt')
      .then(function(resp) {
          // 执行成功
          console.log('执行成功:', resp)
      }, function(err) {
          // 执行失败
          console.log('执行失败:', err)
      })
    

    五、promise 解决回调地狱问题

    以此读取三个文件,出现的回调地狱问题:

    const fs = require('fs')
    
    
    function getFile(file_path) {
        return new Promise(function (resolve, reject) {
            fs.readFile(file_path, 'utf-8', (err, resp) => {
                if (err) return reject(err)     // 失败的回调
                
                // 成功的回调
                resolve(resp)
            })
        })
    
    }
    
    getFile('./files/1.txt')
        .then(function(resp1) {
            // 执行成功
            console.log('1.txt 执行成功:', resp1)
    
            getFile('./files/2.txt')
                .then(function(resp2) {
                    console.log('2.txt 执行成功:', resp2)
    
                    getFile('./files/3.txt')
                        .then(function(resp3) {
                            console.log('3.txt 执行成功:', resp3)
                        })
                })
        })
    

    promise 解决回调地狱

    getFile('./files/1.txt')
        .then(function(resp1) {
            console.log('1.txt 执行成功:', resp1)
    
            return getFile('./files/2.txt')
        })
        .then(function(resp2) {
            console.log('2.txt 执行成功:', resp2)
    
            return getFile('./files/3.txt')
        })
        .then(function(resp3) {
            console.log('3.txt 执行成功:', resp3)
        })
    

    promise 采用的是链式调用,而不是嵌套调用。

    同时指定异常回调:

    getFile('./files/1.txt')
        .then(function(resp1) {
            console.log('1.txt 执行成功:', resp1)
    
            return getFile('./files/2.txt')
        }, function(err1) {
            console.log('读取 1.txt 出错:', err1)
        })
        .then(function(resp2) {
            console.log('2.txt 执行成功:', resp2)
    
            return getFile('./files/3.txt')
        })
        .then(function(resp3) {
            console.log('3.txt 执行成功:', resp3)
        })
    

    注意:异常回调通常可省略!

    六、捕获 promise 中的异常

    当有多个 promise "嵌套使用" 出现异常时,通常会有以下两种处理情形:

    • 前面的 promise 出现异常,不影响后续的 promise 执行:通常给每个 promise 指定异常回调
    • 前面的 promise 一旦出现异常,直接捕获异常,后续的 promise 不执行:通常使用 catch() 捕获异常

    情形一

    // 不存在的文件
    getFile('./files/11.txt')
        .then(function(resp1) {
            console.log('1.txt 执行成功:', resp1)
    
            return getFile('./files/2.txt')
        }, function(err1) {
            console.log('读取 1.txt 出错:', err1)
        })
        .then(function(resp2) {
            console.log('2.txt 执行成功:', resp2)
    
            return getFile('./files/3.txt')
        }, function(err2) {
            console.log('读取 2.txt 出错:', err2)
        })
        .then(function(resp3) {
            console.log('3.txt 执行成功:', resp3)
        }, function(err3) {
            console.log('读取 3.txt 出错:', err3)
        })
    

    运行 node read_file.js,运行结果:

    > node "03. promise 解决回调地狱问题.js"
    读取 1.txt 出错: [Error: ENOENT: no such file or directory, open 'F:200-源码342-Vue.js黑马205集-Vue.jsVue.js 练习day08files11.txt'] {
      errno: -4058,
      code: 'ENOENT',
      syscall: 'open',
      path: 'F:\200-源码\342-Vue.js\黑马205集-Vue.js\Vue.js 练习\day08\files\11.txt'
    }
    2.txt 执行成功: undefined
    3.txt 执行成功: 333
    

    情形二

    getFile('./files/11.txt')
        .then(function(resp1) {
            console.log('1.txt 执行成功:', resp1)
    
            return getFile('./files/2.txt')
        })
        .then(function(resp2) {
            console.log('2.txt 执行成功:', resp2)
    
            return getFile('./files/3.txt')
        })
        .then(function(resp3) {
            console.log('3.txt 执行成功:', resp3)
        })
        .catch(function (err) {
            console.log('执行异常::', err.message)
        }) 
    
    console.log('OK')
    

    运行结果:

    OK
    > node "03. promise 解决回调地狱问题.js"
    执行异常:: ENOENT: no such file or directory, open 'F:200-源码342-Vue.js黑马205集-Vue.jsVue.js 练习day08files11.txt'
    

    注意:当 promise 中发生异常时,不会影响主程序后续的程序运行,上述代码中,会先执行 console.log("OK")

    七、Ajax 中使用 promise

    $(function () {
          $('#btn').on('click', function () {
            $.ajax({
              url: './data.json',
              type: 'get',
              dataType: 'json'
            })
              .then(function (data) {
                console.log(data)
              })
          })
        });
    

    去掉原有的 success(resp),而是使用 then() 来处理 ajax 请求响应。

  • 相关阅读:
    element ui 权限 全选和半选
    div 内容垂直居中
    ajax 传递list2
    mysql学习03-sql执行加载顺序
    mysql学习02-mysql存储引擎(InnoDB,MyISAM)
    mysql学习01-mysql架构
    没有项目的源码,在eclipse下进行tomcat的远程调试,小计一下。
    win10系统,使用SangforHelperTool诊断工具进行修复时,无法安装虚拟网卡。
    postman在有登录认证的情况下进行接口测试!!!
    MongoDB4.0及以上的版本安装时无法启动服务。
  • 原文地址:https://www.cnblogs.com/midworld/p/13611069.html
Copyright © 2020-2023  润新知