精华内容
下载资源
问答
  • 最近在用Node.js编写一个后端逻辑,里面涉及到Mysql的联表查询(即用一个表的查询结果去查另一个表),这时就需要多层回调函数嵌套。那么问题就来了,多层回调函数嵌套就会产生“回调地狱”的问题,代码结构非常难看...

    最近在用Node.js编写一个后端逻辑,里面涉及到Mysql的联表查询(即用一个表的查询结果去查另一个表),这时就需要多层回调函数嵌套。那么问题就来了,多层回调函数嵌套就会产生“回调地狱”的问题,代码结构非常难看,而Promise和async就是为了解决“回调地狱”而产生的解决方案。我选择了Promise,但是在代码结构方面遇到了一些问题,最后经过大佬的指点解决了,特此记录。

    首先要安装mysql模块(在已安装Mysql的前提下):

    npm install -s mysql

    然后执行(这里是我犯的错误,正确代码在后面):

    /*
     注意这是一段错误的代码
    */
    const mysql = require('mysql');
    // 建立连接
    let connection = mysql.createConnection({
      host: '127.0.0.1', // 数据库地址
      port: '3306', // 数据库端口
      user: 'root', // 用户名
      password: '', // 密码
      database: '' // 数据库名称
    });
    // Promise异步执行
    let prom = Promise.resolve();
    prom.then(function () {
      // 执行查询
      connection.query('SELECT * FROM users_table;', (e, result) => { // 这里users_table是我的表名,请读者自行替换
        console.log('Search complete!');
        if (e) {
          throw e;
        }
        connection.end(); // 关闭连接,否则程序不会自动退出
        return Promise.resolve(result);
      });
    })
      .then(function (data) {
        console.log('Search result: ', data);
      });

    输出结果如下:

    Search result:  undefined
    Search complete!

    可以看到,then()方法先执行了,然后mysql才返回结果,说明mysql的异步执行并没有被Promise监视,Promise以为程序已经执行完毕,因此进入下一步了。

    经过继续学习Promise,得到正确的Promise异步执行代码如下:

    const mysql = require('mysql');
    // 建立连接
    let connection = mysql.createConnection({
      host: '127.0.0.1', // 数据库地址
      port: '3306', // 数据库端口
      user: 'root', // 用户名
      password: '', // 密码
      database: '' // 数据库名称
    });
    // Promise异步执行
    let prom = Promise.resolve();
    prom.then(function () {
      // 执行查询
      return new Promise(resolve => {
        connection.query('SELECT * FROM users_table;', (e, result) => { // 这里users_table是我的表名,请读者自行替换
          console.log('Search complete!');
          if (e) {
            throw e;
          }
          connection.end(); // 关闭连接,否则程序不会自动退出
          resolve(result);
        });
      });
    })
      .then(function (data) {
        console.log('Search result: ', data);
      });

    结果:

    Search complete!
    Search result:  [
      // some data
    ]

    执行成功。

    经过总结反思,我对Promise.then()的理解是,then()方法返回一个Promise对象,而then()本身不是异步方法,并没有进行异步回调的监听,所以真正的异步函数应该放在返回的Promise对象中,而Promise对象会对resolve()方法进行监听,实现异步执行。

    展开全文
  • Promise 对象用于异步(asynchronous)计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。 Promise的几种状态: pending:初始状态,即等待操作的执行 fulfilled:成功的操作 rejected:失败的操作...

    Promise的概念

    Promise 对象用于异步(asynchronous)计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。

    Promise的几种状态:

    • pending:初始状态,即等待操作的执行
    • fulfilled:成功的操作
    • rejected:失败的操作

    pending的状态既可以转为fulfilled,也可以转为rejected,当状态发生改变时,promise.then(onFulfilled, onRejected)方法将被调用

    Promise的基本用法

    1.首先创建一个Promise的实例

    var promise = new Promise(function(resolve, reject){
        //do something
        if(success){
            resolve(value);
        } else {
            reject(value);
        }
    });

    构造函数的参数Function中带有两个函数对象resolve和reject,二者都是返回一个Promise对象

    • resolve用在处理执行成功的场景,Promise从pending转为fulfilled状态时调用
    • reject用在处理执行失败的场景,Promise从pending转为rejected状态时调用

    2.调用then()方法

    promise.then(function(value){
        //成功时调用
    }, function(value){
        //失败时调用
    });

    用Promise来封装异步函数

    Node.js中的IO操作都是异步的,因此在写异步程序的过程中容易掉进回调大坑

    知道了Promise的基本调用过程,我们就可以用来封装异步的函数了

    1.定义函数

    function sendRequest(){
        return new Promise(function(resolve, reject){
            var req = http.request(options, function(res){
                var data = '';
                res.on('data', function(chunk){
                    data += chunk;
                });
    
                res.on('end', function(){
                    //成功后调用
                    resolve(data);
                });
            });
    
            req.on('error', function(err){
                //失败后调用
                reject(err);
            });
    
            req.end();
        });
    }

    2.调用函数

    sendRequest().then(function(data){
        console.log(data);
    }).catch(function(err){
        console.log(err);
    });

    参考

    展开全文
  • 异步编程之异步函数 一、简介 node.js是一个Javascript运行环境(runtime environment),实质是对Chrome V8引擎进行了封装;node.js不是一个 JavaScript 框架,也不是浏览器端的库,node.js是一个让 JavaScript 运行...

    异步编程之异步函数

    一、简介

    node.js是一个Javascript运行环境(runtime environment),实质是对Chrome V8引擎进行了封装;node.js不是一个 JavaScript 框架,也不是浏览器端的库,node.js是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。

    1.1 特点

    • 异步IO
    • 事件与回调函数
    • 单线程(javascript语言的特点)
    • 跨平台

    1.2 异步IO

    本文着重讲解异步编程中的异步函数,由于JS的运行机制是单线程异步执行程序
    示例:
    在这里插入图片描述

    在这里插入图片描述

    所以在程序设定时会涉及大量异步函数,此时ES6给我们提供了Promise对象去封装异步操作。

    const fs = require('fs');
    function p1() {
        // 返回promise对象
        return new Promise((reslove,reject)=>{
        fs.readFile('./1.txt','utf-8',(err,result)=>{
            if(err!=null){
                // 传给外部then方法
                reject(err);
            }else{
                // 传给外部catch方法
                reslove(result);
            }
        })
    })
    }
    function p3() {
        // 返回promise对象
        return new Promise((reslove,reject)=>{
        fs.readFile('./3.txt','utf-8',(err,result)=>{
            if(err!=null){
                // 传给外部then方法
                reject(err);
            }else{
                // 传给外部catch方法
                reslove(result);
            }
        })
    })
    }
    function p2() {
        // 返回promise对象
        return new Promise((reslove,reject)=>{
        fs.readFile('./2.txt','utf-8',(err,result)=>{
            if(err!=null){
                // 传给外部then方法
                reject(err);
            }else{
                // 传给外部catch方法
                reslove(result);
            }
        })
    })
    }
    
    p1()
    .then((res)=>{//接收reslove传过来的参数
        console.log(res);
        return p2();
    })
    .then(res=>{//接收reslove传过来的参数
        console.log(res);
        return p3();
    })
    .then(res=>{//接收reslove传过来的参数
        console.log(res);
    })
    

    虽然ES6提供对的promise对象有效解决了回调地狱以及更方便的回调函数解决方案,但这代码总会出现过长且重复代码过多的问题,于是ES7给我们提供了一个promise的语法糖——async/await,这个为我们节省了大量的代码空间。接下来就介绍一下这个使用的语法糖:
    异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了

    const fn = async ()=>{};
    //等同于
    async function fn() {}
    

    async关键字

    1. 普通函数定义前加async关键字 普通函数变成异步函数
    2. 异步函数默认返回promise对象
    3. 异步函数内部使用return关键字返回结果 结果会被包裹在promise对象中 return关键字代替了resolve方法
    4. 异步函数内部使用throw关键字抛出异常
    5. 调用异步函数再调用then方法获取异步函数执行结果
    6. 调用异步函数再调用catch方法获取异步函数执行的错误信息
    async function fn() {
    	throw '发生了一些错误'return 123;
    }
    
    fn().then((data)=>{
    	console.log(data);
    }).catch(err=>{
    	console.log(err);
    })
    

    await关键字

    1. await关键字只能出现在异步函数中
    2. await promise await后面只能写promise对象 写其他类型的API是不可以的
    3. await 关键字可暂停异步函数向下执行 直到promise返回结果
    async function p1() {
    	return 'p1';
    }
    async function p2() {
    	return 'p2';
    }
    async function p3() {
    	return 'p3';
    }
    async function run() {
    	let r1= await p1();
    	let r2=await p2();
    	let r3=await p3();
    	console.log()    
    }
    
    run();
    

    nodejs中异步函数的应用

    const fs = require('fs');
    //改造现有异步函数api  让其返回promise对象 从而支持异步函数语法
    const promisify = require('util').promisify;
    // 调用promisify 方法改造现有异步API  让其返回promise对象
    const readFile = promisify(fs.readFile);
    
    async function run() {
    	let r1 = await readFile('./1.txt','utf8');
    	let r2 = await readFile('./2.txt','utf8');
    	let r3 = await readFile('./3.txt','utf8');
    	console.log(r1)
    	console.log(r2)
    	console.log(r3)
    }
    
    run();
    

    总结

    异步函数的目的是为了让代码 的可读性更高,并且让异步执行函数在一定条件下成为同步执行函数。这样既方便代码的可执行性,也提高了代码的可读性。

    展开全文
  • Promise异步函数

    2020-05-19 16:00:17
    // 同步代码在执行时,这个setTimout也会执行,只不过回调函数当前不会调用,会先推入到异步回调队列中,等达到执行条件了,就会调用 setTimout(() => { console.log(2) }, 1000) console.log(3) 回调地狱:指...

    node

    同步、异步API的概念:

    同步API:从上往下执行,当前代码执行完后,才会继续往下执行,范例:

    console.log(1)
    console.log(2)
    // 1
    // 2
    

    异步API:当前代码的执行不会阻塞后续代码的执行,范例:

    console.log(1)
    setTimeout(() => {
    	console.log(2)
    }, 1000)
    console.log(3)
    // 1
    // 3
    // 等待1秒后
    // 2
    

    同步API我们是可以直接用返回值获取结果的,但是异步API是不行的,异步API需要用回调函数的形式,用回调函数的形参接收返回结果

    console.log(1)
    // 同步代码在执行时,这个setTimout也会执行,只不过回调函数当前不会调用,会先推入到异步回调队列中,等达到执行条件了,就会调用
    setTimout(() => {
      console.log(2)
    }, 1000)
    console.log(3)
    

    回调地狱:指的是多个依次的异步操作,说白了就是回调函数嵌套,当嵌套层次过多,不利于阅读和维护

    Promise基本使用:

    const fs = require('fs')
    // 这个resolve和reject是我们自己定义名字,你可以改成其他,但是不推荐,业内约定俗成就叫这个
    const p = new Promise((resolve, reject) => {
      fs.readFile('./hehe.txt', 'utf8', (err, data) => {
        if (err) {
          reject(err)
        } else {
          resolve(data)
        }
      })
    })
    
    p.then((data) => {
      // 异步API执行正确,拿到正确的数据
    	// your code . do something...
    }).catch((err) => {
      // 异步API执行异常,拿到错误的数据
      // your code... do something...
    })
    
    • Promise就是用来解决回调地狱的,,它不是一个新的技术,只是一种手段,是异步编程的中间产物
      • 原理:把一个异步API封装起来,将异步API的结果以回调函数的形式传递出去
    • 可以通过new Promise( ( resolve, reject ) => { … }) 创建Promise实例
      • 注意:创建实例时,并不会执行( resolve, reject ) => { ... }回调函数,也就意味着内部的代码都不会执行,只有在调用then或catch方法的时候才会去调用
    • 可以通过resolve( result )方法传递正确的结果
    • 可以通过reject( err )方法传递错误的结果
    • 通过调用Promise实例的then(( result ) => { … })方法接收正确的结果
    • 通过调用Promise实例的catch(( err ) => { … })方法接收错误的结果

    解决回调地狱:

    const fs = require('fs')
    
    // 想要依次读取1.txt,2.txt,3.txt的文件内容
    
    // fs.readFile('./1.txt', 'utf8', (err, data) => {
    //   console.log(data)
    //   fs.readFile('./2.txt', 'utf8', (err, data) => {
    //     console.log(data)
    //     fs.readFile('./3.txt', 'utf8', (err, data) => {
    //       console.log(data)
    //     })
    //   })
    // })
    
    // new Promise(cb) 实例时,并不会调用这个 cb 函数
    // 只有在调用了Promise实例的then方法或catch方法,才会调用cb函数
    const p1 = new Promise((yes, no) => {
      fs.readFile('./1.txt', 'utf8', (err, data) => {
        yes(data)
      })
    })
    
    const p2 = new Promise((yes, no) => {
      fs.readFile('./2.txt', 'utf8', (err, data) => {
        yes(data)
      })
    })
    
    const p3 = new Promise((yes, no) => {
      fs.readFile('./3.txt', 'utf8', (err, data) => {
        yes(data)
      })
    })
    
    // then函数的返回值 就是 其参数(回调函数)的返回值
    p1.then(data => {
      console.log(data)
      return p2
    }).then(data => {
      console.log(data)
      return p3
    }).then(data => {
      console.log(data)
    })
    

    异步函数(ES7添加的):

    • async关键字:
      • 在普通函数前面加上async关键字,该普通函数就变成了异步函数
      • 异步函数的返回值会被包装成一个Promise实例
        • return传递正确的结果,相当于Promise里面的resolve函数
        • throw传递错误的结果,相当于Promise里面的reject函数,一旦抛出错误,后面的代码就不会执行了
    • await关键字:
      • await后面一般跟Promise实例(其实也可以跟其他的数据,如果是其他的数据,则直接返回),await可以阻塞后续的代码,等待Promise实例返回结果后,再继续向下执行
      • await可以直接拿到Promise实例的正确结果,错误结果需要用try ... catchcatch(err => err)(推荐用这个)来获取
      • await只能出现在异步函数(亲爸爸)中

    范例:用async、await关键字改造依次读取1.txt、2.txt、3.txt文件的代码:

    const fs = require('fs')
    // promiseify可以将node中现有的基于回调函数形式的异步API,改造成返回Promise实例的函数
    const { promiseify } = require('util')
    
    // fs.readFile('./1.txt', 'utf8', (err, data) => { ... })
    const readFileOfPromise = promiseify(fs.readFile)
    
    (async () => {
     	const data1 = await readFileOfPromise('./1.txt', 'utf8')
      console.log(data1)
      const data2 = await readFileOfPromise('./2.txt', 'utf8')
      console.log(data2)
      const data3 = await readFileOfPromise('./3.txt', 'utf8')
      console.log(data3)
    })()
    

    代码块演示

    在这里插入图片描述

    异步执行机制图

    在这里插入图片描述

    展开全文
  • 2021.3.1 文章目录Node.js(二)请求响应原理及HTTP协议服务器端...异步API同步API,异步API的区别1(获取返回值)回调函数同步API,异步API的区别2(代码执行顺序)Node.js中的异步API回调地狱Promise异步函数 Node.j.
  • 在ES7中新增了异步函数语法,异步函数异步API语法的终极解决方案,没有再比这个更简易的了,异步函数可以让我们将异步代码写成同步的形式,让代码不再有回调函数。 基础语法: // 普通函数 function fn(){ ...
  • node.js 异步函数

    2020-11-04 14:48:03
    异步函数异步编程语法的终极解决方案,它可以让将异步代码写成同步的形式...在异步函数内部使用return关键字进行结果返回,结果会被包裹的promise对象中,return关键字代替了resolve方法 在异步函数内部使用throw关键
  • Promise出现的目的是解决Node.js异步编程中回调地狱的问题。 需求:依次读取1.txt、2.txt、3.txt文件 const fs = require('fs'); fs.readFile('./1.txt', 'utf8', (err, result1) => { console.log(result1) ...
  • 在写Node.js的过程中,连续的IO操作可能会导致“金字塔噩梦”,回调函数的多重嵌套让代码变的难以维护,利用CommonJs的Promise来封装异步函数,使用统一的链式API来摆脱多重回调的噩梦。  Node.js提供的非阻塞IO...
  • 要保证是依次读取,所以我们需要回调函数嵌套来保证是依次读取1.txt、2.txt、3.txt文件 const fs = require('fs'); fs.readFile('./1.txt', 'utf8', (err, result1) => { console.log(result1); fs.readFile('...
  • 有a、b、c三个异步任务,要求必须先执行a,再执行b,最后执行c 且下一次任务必须要拿到上一次任务执行的结果,才能做操作 解决 方法一(使用then链式操作)特点:可以满足需求,但是书写比较繁琐 代码var a = function...
  • node.js中fs 模块库操作文件的方法都是异步的 setTimeout是异步 如果需要得到异步函数的操作结果,必须通过回调函数来获取. 1.那我们怎么获取文件的内容呢? 通过回调函数callback来获取 回调函数就是为了获取...
  • Node.js异步函数处理

    2020-11-01 16:35:11
    以此类推,反复嵌套,由于setTimeout是异步函数,故会一直回调一直回调。从而产生回调地狱 解决方法 1 Promise 我们先学习Promise对象 let promise=new Promise((resolve,reject)=>{ if(true)resolve(
  • // 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法 const promisify = require('util').promisify; // 调用promisify方法改造现有异步API 让其返回promise对象 const readFile = promisify(fs
  • node异步执行

    2018-02-26 10:49:01
    为了协调异步任务,Node提供了四个定时器,让任务可以在指定的时间运行。 ● setTimeout() ● setInterval() ● setImmediate() ● process.nextTick() 复制代码 前两个是js语言的标准,后两个是 Node ...
  • node中的异步处理(前端异步流程) 1. 为什么进行异步操作? - javascript为单线程,一次执行一个任务 2. 前端异步的操作模式 - 传统方式(回调函数/事件) - 前端异步流程工具(封装出来的函数库) - es6 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,499
精华内容 6,999
关键字:

nodepromise异步执行函数