如何在 NodeJS 中控制应用程序的流动

Posted

技术标签:

【中文标题】如何在 NodeJS 中控制应用程序的流动【英文标题】:How to control the flow of applications in NodeJS 【发布时间】:2017-10-30 00:29:08 【问题描述】:

我正在用 nodeJS 编写我的第一个应用程序。我正在写一个电报机器人,我想知道如何控制应用程序的流程,因为它是异步的。我来自 php 背景,一切都很简单,程序化,一个接一个。

比方说,在我的机器人中,当收到任何消息时,首先程序必须确保用户详细信息在缓存或数据库中,然后再继续。检查完成后可以继续。

我打算通过使用一个变量作为标志来做到这一点,但由于 javascript 的异步特性,它无法做到。我不知道该怎么做。我是否将侦听器分配给对象并发出事件来控制流程?

这是我的代码

    const fs = require('fs');

// Establish connection with cache and database
const mysql = require('mysql-wrapper');
const Memcached = require('memcached');
const memcached = new Memcached('localhost:11211');
const bb = require('bot-brother');

var settings = 
    host: 'localhost',
    database: 'test',
    user: 'root',
;
var qb = require('node-querybuilder').QueryBuilder(settings, 'mysql', 'single');

//Load the database cache functions
const dbc = require("./dbc");
dbc.memcached = memcached;
dbc.mysqc = qb;

//Load the user handling functions 
const user = require("./user");
user.dbc = dbc;

const bot = bb(
    key : '331263599:AAHmLl4Zcg4sKGnz7GNzacgkJl1W8lwz33c',
    polling:  interval: 0, timeout: 1 
);

//code that checks user existence in cache/db
bot.api.on('message', (msg)=>
    console.log(msg.from);
    var userData = msg.from;
    var tid = userData.id;
    //Check if user is in cache 
    user.check_user_existence(tid,function(re)
        if(re < 2)
            user.complete_user_existence(re,userData,function(err,response)
                if(err)
                    bot.api.sendMessage(tid,"Sorry an unexpected error occured!");
                 else 
                    console.log('ha');
                    play = 1;
                
            );
         

    );
);


//Code to be run after checking 
if(play==1)
    send_another_message();
    do_some_things();

【问题讨论】:

您可能想看看如何在 node.js(或一般的 javascript)中使用 async/await 和 promises。这里稍微介绍一下:blog.readme.io/using-async-await-in-node-js-7-6-0 很棒的线路,I come from a php background where everything was simple, procedural, one after the other. 喜欢它。 【参考方案1】:

您可以使用回调或承诺 您可以使用异步模块或互斥锁

如果您需要序列化一些异步函数,您可以使用以下方法之一:

Callback

Native promises

Bluebird promise

Async module

Callback 和 Promise 主要用于相关函数,第二个函数需要第一个函数。bluebird 是一个用于创建 Promise 并对其进行完全自定义的模块。

异步模块是异步运行函数并一起获取结果的好方法。

如果您在单个对象或文件中进行异步写入,则最后一种方法是 Mutex,您需要锁定释放方法

【讨论】:

【参考方案2】:

您可以通过nsynjs 同步运行代码。您的代码可能会像这样转换:

步骤 1. 将带有回调的慢速函数包装到支持 nsynjs 的包装器中:

// content of wrappers.js
user = require("./user");
exports.user_check_user_existence_wrapper = function (ctx, uid) 
    var res = ;

    user.check_user_existence(tid,function(re)
        res.re = re;
        ctx.resume();
    )

    return res;
;
exports.user_check_user_existence_wrapper.nsynjsHasCallback = true;

exports.user_complete_user_existence_wrapper = function(ctx, re, userData) 
    var res = ;

    user.complete_user_existence(tid,function(error,ue_response)
        res.error = error;
        res.ue_response = ue_response;
        ctx.resume(error); // if error is set, it will cause exception in the caller
    )

    return res;
;
exports.user_complete_user_existence_wrapper.nsynjsHasCallback = true;

步骤 2. 将同步逻辑放入函数中,使用上面的包装器执行慢速函数:

var synchronousCode = function(wrappers,msg) 
    console.log(msg.from);
    var userData = msg.from;
    var tid = userData.id;
    //Check if user is in cache 
    var re = wrappers.user_check_user_existence_wrapper(nsynjsCtx,tid).re;
    if(re < 2)
        try 
            var res = wrappers.user_complete_user_existence_wrapper(re,userData).ue_response;
            console.log('ha');
            play = 1;
        
        catch (e) 
            bot.api.sendMessage(tid,"Sorry an unexpected error occured!",e);
        ;

第 3 步。通过 nsynjs 运行您的同步函数:

var nsynjs = require('nsynjs');
var wrappers = require('./wrappers');
var synchronousCode = function(wrappers,msg) 
....


bot.api.on('message', function(msg) 
    nsynjs.run(synchronousCode,,wrappers,msg,function()
        console.log('synchronousCode finished');
    )
);

请在此处查看更多示例:https://github.com/amaksr/nsynjs/tree/master/examples/node-module-loading

【讨论】:

以上是关于如何在 NodeJS 中控制应用程序的流动的主要内容,如果未能解决你的问题,请参考以下文章

如何设置推送和弹出视图控制器流程

Node的内存控制

如何在 Nodejs 调试控制台视图中更改对象的字符串表示

对于Passenger,控制台日志(从puts的输出)去哪里......对于Nodejs

如何在NodeJS中以单行控制台日志格式制作实时时钟[重复]

我还应该使用啥来替代 nodejs 中的控制台?