NodeJS中如何处理好异步API

简介: NodeJS中如何处理好异步API

异步编程 - 如何控制好异步过程


参考资料 阮一峰 Javascript异步编程的4种方法)


  • JS的执行环境是单线程(Single thread)


  • I/O处理需要回调函数异步处理 (异步I/O)


  • 前端异步IO可以消除UI阻塞,提高用户体验


  • 而放在后端则可以提高CPU和内存里利用率


串联异步处理


异步操作队列化,按照期望的顺序执行。


Callback


回调地域太可怕


const logTime = (name) => {
    console.log(`Log....${name}   ` + new Date().toLocaleTimeString())
}
exports.callback = () => {
    setTimeout(() => {
        logTime('callback 1')
        setTimeout(() => {
            logTime('callback 2')
        }, 100)
    }, 100)
}


测试代码


test('callback', done => {
  callback()
  // 延时4s结束
  setTimeout(done, 1000)
})


Promise


The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future.


译文:Promise对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。


说白了就是一个异步执行的状态机,异步执行的承诺。


const promise = (name, delay = 100) => new Promise(resolve => {
    setTimeout(() => {
        logTime(name)
        resolve()
    }, delay)
})
exports.promise = () => {
    promise('Promise1')
        .then(promise('Promise2'))
        .then(promise('Promise3'))
        .then(promise('Promise4'))
}


Gennerator


ES6 新引入了 Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。 基本


  • function -> function* 称为Gennerator函数


  • 函数内部有 yield 表达式。


function* func() {
    console.log("one");
    yield '1';
    console.log("two");
    yield '2';
    console.log("three");
    return '3';
}
const f = func()
f.next();
// one
// {value: "1", done: false}
f.next();
// two
// {value: "2", done: false}
f.next();
// three
// {value: "3", done: true}
f.next();
// {value: undefined, done: true}
// 或者通过迭代器
for (const [key,value] of func()) {
    console.log(`${key}: ${value}`);
}


逻辑代码


let co = function (gen, name) {
    var it = gen(name)
    var ret = it.next()
    ret.value.then(function (res) {
        it.next(res)
    })
}
exports.generator = () => {
    const generator = function* (name) {
        yield promise(name + 1)
        yield promise(name + 2)
        yield promise(name + 3)
        yield promise(name + 4)
    }
    let co = generator => {
        if (it = generator.next().value) {
            it.then(res => {
                co(generator)
            })
        } else {
            return
        }
    }
    co(generator('Co-Generator'))
}


async/await


async/await是es7推出的一套关于异步的终极解决方案


  • 任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。


  • async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。


exports.asyncAwait = async () => {
    await promise('Async/Await1')
    await promise('Async/Await2')
    await promise('Async/Await3')
    await promise('Async/Await4')
}


事件监听方式处理


采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。


exports.event = async () => {
    const asyncFun = name => event => {
        setTimeout(() => {
            logTime(name)
            event.emit('end')
        }, 100)
        return event
    }
    const ary = [
        asyncFun('event1'),
        asyncFun('event2'),
        asyncFun('event3')
    ]
    const { EventEmitter } = require('events')
    const event = new EventEmitter()
    let i = 0
    event.on('end', () => i < ary.length && ary[i++](event))
    event.emit('end')
}


eventEmmiter


const promise = (name, delay = 100) => new Promise(resolve => {
    setTimeout(() => {
        logTime(name)
        resolve()
    }, delay)
})
exports.promise = () => {
    promise('Promise1')
        .then(promise('Promise2'))
        .then(promise('Promise3'))
        .then(promise('Promise4'))
}


扩展阅读eventEimitter源码解析 / 订阅发布机制


class EventEmitter {
    constructor() {
        this.handler = {};
    }
    on(eventName, callback) {
        if (!this.handles) {
            this.handles = {};
        }
        if (!this.handles[eventName]) {
            this.handles[eventName] = [];
        }
        this.handles[eventName].push(callback);
    }
    emit(eventName, ...arg) {
        if (this.handles[eventName]) {
            for (var i = 0; i < this.handles[eventName].length; i++) {
                this.handles[eventName][i](...arg);
            }
        }
    }
}
const event = new EventEmitter(); 
event.on('some_event', num =>  { 
    console.log('some_event 事件触发:'+num); 
}); 
let num = 0
setInterval(() =>  { 
    event.emit('some_event' , num ++ ); 
}, 1000);


RxJS


对于事件流的控制 -- 近期推出 --



相关文章
|
7月前
|
JavaScript API
使用Node.js访问API的示例
下面是一个使用Node.js访问API的示例代码:
|
2月前
|
Web App开发 JavaScript NoSQL
深入浅出:构建基于Node.js的RESTful API
在当今快速发展的互联网时代,RESTful API已成为前后端分离架构中不可或缺的一部分。本文旨在为初学者和中级开发人员提供一个清晰、简洁的指南,详细介绍如何使用Node.js构建一个高效、可维护的RESTful API。通过结合实际案例,本文将从API设计理念出发,深入讲解如何利用Express框架及MongoDB数据库实现API的增删改查功能,同时探讨如何通过JWT进行安全认证,确保数据传输的安全性。此外,文章还将简要介绍如何使用Swagger生成API文档,使得API的测试和维护更加便捷。无论你是希望提升现有项目的API设计,还是想从零开始构建一个新项目,本文都将为你提供一条清晰的道路
|
1月前
|
Web App开发 JavaScript 前端开发
使用Node.js和Express构建RESTful API
使用Node.js和Express构建RESTful API
19 0
|
2月前
|
NoSQL JavaScript 前端开发
深入浅出:使用Node.js和MongoDB构建RESTful API
在当今的软件开发领域,构建高效、可扩展的Web服务已成为开发者的重要任务之一。本文将引导读者通过现代JavaScript环境——Node.js,搭配流行的NoSQL数据库MongoDB,一步步构建一个RESTful API。不同于常规的摘要,我们将采用故事化的方式,通过一个虚构的应用“BookFinder”的开发旅程,带领读者理解API设计、数据库交互及安全性考量等关键知识点。无论你是前端工程师希望深化后端知识,还是后端新手寻求实践机会,本文都将提供你所需的指南和启示。
|
7月前
|
数据库连接 API Python
RESTful API 如何处理异常
RESTful API 如何处理异常
|
3月前
|
Web App开发 前端开发 测试技术
【Web API系列】使用异步剪贴板API(async clipboard)的图像的编程复制和粘贴
【Web API系列】使用异步剪贴板API(async clipboard)的图像的编程复制和粘贴
77 1
|
3月前
|
消息中间件 Kafka API
Kafka - 异步/同步发送API
Kafka - 异步/同步发送API
45 0
|
8月前
|
消息中间件 负载均衡 Kafka
Kafka学习---2、kafka生产者、异步和同步发送API、分区、生产经验(一)
Kafka学习---2、kafka生产者、异步和同步发送API、分区、生产经验(一)
|
4月前
|
JavaScript API 网络架构
Node.js RESTful API如何使用?
Node.js RESTful API如何使用?
77 0
|
4月前
|
缓存 监控 算法
如何处理1688商品详情API的并发请求问题?
并发请求问题是指在多个用户同时对同一资源进行操作时,产生的冲突和竞争条件。在1688商品详情API的应用场景下,多个用户可能同时对同一商品信息进行查询或更新。如果这些操作没有得到合理的协调和处理,就可能导致数据的不一致性和错误。