How to share variables in promise chain?

Time:2020-11-29

Translator’s note:usePromiseI’ll find out if I write asynchronous codePromiseSharing variables in a chain is a big headache, and that’s also trueAsync/AwaitBetter thanPromiseWe have mentioned six reasons for async / await to replace promise, which will be more detailed in this blog.

  • Passing data between promise callbacks
  • Translator: fundebug

In order to ensure the readability, this paper uses free translation instead of literal translation, and makes a lot of modifications to the source code. In addition, the copyright of this paper belongs to the original author, and the translation is only used for learning.

When writing asynchronous code based on promise, you usually use multiplethenMake up a chain call, eachthenThere will be a callback function. Therefore, in the promise chain, there are many callback functions, and each callback function has an independent variable scope. So how do you share variables among these callback functions? This blog will explore this issue.

problem

connectionVariable inADefined inBandCYou need to use it everywhere. However, due toA、B、CThey are in their own independent scopes,connectionVariables will not be available inBandCIt can be used directly.

db.open()
    .then(connection => // A
    { 
        return connection.select(
        {
            name: 'Fundebug'
        });
    })
    .then(result =>
    {
        connection.query(); // B
    })
    .catch(error =>
    {
        // ...
    })
    .finally(() =>
    {
        connection.close(); // C
    });

Method 1: use high-order scoped variables

Scope definition in higher orderconnectionVariable, inDIn this way, theBandCIt’s used directly.

let connection; // A
db.open()
    .then(conn =>
    {
        connection = conn; // D
        return connection.select(
        {
            name: 'Fundebug'
        });
    })
    .then(result =>
    {
        connection.query(); // B
    })
    .catch(error =>
    {
        // ...
    })
    .finally(() =>
    {
        connection.close(); // C
    });

problem: if you need to share too many variables (which is a common case), you need to define many variables in the high-order scope, which is very troublesome and redundant.

Method 2: nested scopes

Will need to useconnectionThe promise chain of variables is embedded into the correspondingthenIn the callback functionBandCIt’s used directly.

db.open()
    .then(connection => // A
        {
            return connection.select(
                {
                    name: 'Fundebug'
                })
                .then(result =>
                {
                    connection.query(); // B
                })
                .catch(error =>
                {
                    // ...
                })
                .finally(() =>
                {
                    connection.close(); // C
                });
        });

Question:The reason why promise is used is to avoid callback region and convert multi nested callback functions into chained then calls. If nested writing is used to share variables, what is the use of promise?

Method 3: return multiple values

intermediateVariable inADefine and assign a value in theBHowever, due toAAndBIn different scopes,BIt can’t be used directlyintermediateVariable:

return asyncFunc1()
    .then(result1 =>
    { 
        const intermediate = ··· ; // A
        return asyncFunc2();
    })
    .then(result2 =>
    { 
        console.log(intermediate); // B
    });

stayAUse ofPromise.allTo return multiple values, theintermediateThe value of the variable is passed toBDepartment:

return asyncFunc1()
    .then(result1 =>
    {
        const intermediate = ···; 
        return Promise.all([asyncFunc2(), intermediate]); // A
    })
    .then(([result2, intermediate]) =>
    {
        console.log(intermediate); // B
    });

Question:usePromise.allIt seems ingenious to pass shared variables, but it is a bit overqualified and unreasonable; it is not possible to transfer variables to.catch()Andfinally()When there are too many shared variables or need to span several.then(), needreturnWill be a lot.

Method 4: use async / await

Async/AwaitIs a new way to write asynchronous code, can replacePromise, it makes asynchronous code look like synchronous code, and multiple asynchronous operations can be written in the same scope, so there is no problem of passing shared variables!!!

The example in method 1 can be rewritten as follows:

try
{
    var connection = await db.open(); // A 
    const result = await connection.select(
    {
        name: 'Fundebug'
    });
    connection.query(); // B
}
catch (error)
{
    // ...
}
finally
{
    connection.close(); // C
}

The example in method 3 can be rewritten as follows:

try
{
    result1 = await asyncFunc1();
    const intermediate = ··· ;
    result2 = await asyncFunc2();
    console.log(intermediate);
}
catch (error)
{
    // ...
}

Needless to say,Async/AwaitIt is undoubtedly a better way to eliminate the problem directly!

reference resources

  • Promises for asynchronous programming
  • ES proposal: Promise.prototype.finally()
  • ES proposal: Promise.try()
  • Six reasons for async / await to replace promise

How to share variables in promise chain?

Copyright notice:
Please indicate the author fundebug and the address of this article:
https://blog.fundebug.com/201…

Recommended Today

Talking about Java collection

preface Most programming languages provide array to save objects, and array is one of the most important data structures. However, the length of the array has been defined during initialization, which is immutable and troublesome to use. Therefore, Java inJDK 1.2The collection framework is added to the version to save and manipulate objects. The container […]