search

Home  >  Q&A  >  body text

javascript - A problem encountered when nodejs implements asynchronous implementation

For example, there are three functions a, b, and c, all of which perform synchronization operations. In order to simplify it, I have simplified the synchronization operations

function c(m) {
    m = m + 1;
    return m;
}
function b(m) {
    m = m + 1;
    return c(m);
}
function a(){
    let m = 0;
    return b(m);
}

The output of executing a() is 2
But if the c function executes not a synchronous function, but an asynchronous operation, for example

function c(m) {
    setTimeout(function () {
        m = m + 1;
    }, 1000)
    return m;
}

When executing a(), if you want to correctly output 2, you must encapsulate c through promise or async,
Similar to

function promiseC(m) {
    return new Promise((resolve, reject) => {
        setTimeout(function () {
        m = m + 1;
        resolve(m);
        }, 1000)
    }
}
async function c(m) {
    m = await promiseC(m);
    return m; 
}

Because c becomes an asynchronous function, b needs to call c, b must also be changed to asynchronous, and so on, a must also be changed to asynchronous

async function b(m) {
    m = m + 1;
    return await c(m);
}
async function a(){
    let m = 0;
    return await b(m);
}

a().then(function(data) {

console.log(data)

}) In this way, 2

can be output

In order to output 2 correctly, I changed both a and b. I wonder if there is any other way to avoid changing a and b and achieve the correct output?
Since I didn’t consider asynchronous situations when I first wrote the code, functions like a and b are distributed in different files, and there are a lot of them. Now in order to allow c to perform asynchronous operations, it is too difficult to change. I don’t know if you have any other good methods?

The following is a newly added question
The above problems can be solved by directly returning the promise object in the answer below, but the actual code structure is more like this

function c(m) {
    m = m + 1;
    return m;
}
function b(m) {
    m = m + 1;
    let n = c(m)
    n = n + 1
    return n;
}
function a(){
    let m = 0;
    let k = b(m);
    k = k + 1;
    return k;
}

If I follow this method, I have to modify the return methods of a and b.
In order to allow a and b to return promise objects,
I don’t know if there is any way to achieve correct output without changing the a and b functions for such a structure. Methods

黄舟黄舟2730 days ago894

reply all(6)I'll reply

  • 阿神

    阿神2017-07-03 11:43:44

    I’m sorry to tell you that node is explicitly asynchronous, so if you change a function from synchronous to asynchronous, then the functions that depend on it must also be changed. It is indeed a headache when refactoring, but you still have to endure it. Let's change it.

    Refactoring like fibjs, which does not require the async keyword, is very worry-free. If you change c, you don’t need to change a and b, because implicit asynchrony does not require you to indicate it.

    reply
    0
  • PHP中文网

    PHP中文网2017-07-03 11:43:44

    I still don’t understand Promise well enough. There is no need to change b() and a() here.

    For function c, you only need to return a promise object. When passing function b, this Promise object is directly returned synchronously. There is no need to change function b to make it an asynchronous function, because the asynchronous operation is in function c In , only synchronization operations are performed in b. At this time, you need to capture this Promise in function a, so the code can be changed to this

    function promiseC(m) {
        return new Promise((resolve, reject) => {
            setTimeout(function () {
                m = m + 1;
                resolve(m);
            }, 1000)
        })
    }
    
    
    function c(m) {
        m = promiseC(m);
        return m;
    }
    
    function b(m) {
        m = m + 1;
        return c(m);
    }
    function a() {
        let m = 0;
        return b(m);
    }
    
    p.then(function(a){
        console.log(a)
    })

    So, if the functions a(), b()do not handle the return value of asynchronous operations, why should they be changed to Async functions?

    reply
    0
  • 扔个三星炸死你

    扔个三星炸死你2017-07-03 11:43:44

    You can try http://fibjs.org/docs/manual/... and convert it directly to synchronization

    reply
    0
  • 滿天的星座

    滿天的星座2017-07-03 11:43:44

    I have to say that I stared at the screen and made many drafts, but in the end I failed.

    I can’t think of any way to block the current function in js but still execute the resolve of the promise in time. The idea of ​​failure is as follows

    c_result=null
    c=async (m)=>{return m+1}
    c_sync = (m)=>{
        let n=0
            pc=c(m).then((m)=>{c_result=m})
        while(c_result===null && n++<100){}
        return c_result
    }
    b=(m)=>{return c_sync(m+1)}
    a=()=>{return b(0)}
    a()

    The problem is that although while(c_result===null && n++<100){} blocks the function c_sync, it also blocks the execution of the .then callback. Due to the single-threaded asynchronous mechanism, When a certain callback is triggered, if the thread is busy, the callback cannot jump into the queue. As a result, c_result cannot be assigned to the variable m during the execution of the loop. Therefore, there is no way to exit the loop.

    But I think this question is very interesting. I found a related article. The author solved the problem of local blocking through an external binary library.

    http://blog.csdn.net/xingqili...

    My understanding is:
    Based on the event loop of the js engine itself, we cannot block a certain block. Because for the js code, the engine's event loop is at the bottom. But for external binary modules, it can block itself, And ensure that the event loop of the js engine completely traverses the event queue every time----to ensure that new events in the js engine can be processed during its own blocking period.

    reply
    0
  • 巴扎黑

    巴扎黑2017-07-03 11:43:44

    Let a() output promise can indeed solve the problem I mentioned
    But when I actually modified the code, I found that the structure of most of the code was not like my problem above
    but the newly added structure below

    function c(m) {
        m = m + 1;
        return m;
    }
    function b(m) {
        m = m + 1;
        let n = c(m)
        n = n + 1
        return n;
    }
    function a(){
        let m = 0;
        let k = b(m);
        k = k + 1;
        return k;
    }

    reply
    0
  • 世界只因有你

    世界只因有你2017-07-03 11:43:44

    With all due respect, you do not have a deep understanding of the event loop mechanism and event core module of node.js.
    promise and aysnc/await are indeed the mainstream in handling asynchronous process control today, but it does not mean that it cannot be done without them. Such simple problems can be handled back to the event method.

    const EventEmitter = require('events');
    class MyEmitter extends EventEmitter {}
    const myEmitter = new MyEmitter();
    
    myEmitter.on('a', (m) => {
        console.log('a -> b');
        myEmitter.emit('b', m+1);
    });
    myEmitter.on('b', (m) => {
        console.log('b -> c');
        myEmitter.emit('c', m+1);
    });
    myEmitter.on('c', (m) => {
        console.log('result', m);
    });
    myEmitter.emit('a', 0);
    

    reply
    0
  • Cancelreply