0

Evening Everyone,

New to javascript and trying to execute this same order, that is clearly not happening. When I run in debug mode and when i set the debug point on getMongoField the rest of the code gets executed, How do i make this code execute in the same order, first retrieve some fields from mongo and then sendFirstmessage and then sendSecondMessage(all three functions returns a promise), can introduce await inside promise?

Thank you

sentTest: (message) => {
    return new Promise((resolve, reject) => {
        let mongoRecord = null;
        let asResponse;
        let doc = getMongoField('terminals', {'attributes.XYZ': 'ABC'}).then(function (docs) {
            console.info('Before ', mongoRecord)
            mongoRecord = docs
            console.info('After', mongoRecord)
        })

        ts.sendFirstMessage(mongoRecord.attributes.sno, mongoRecord, mongoRecord.attributes.value).then(function (result) {
        //do nothing
        })

        ts.SendSecondMessage(docs.attributes.sno, 'Test', docs, message).then(function (response) {
            resolve(response);
        })

    })
},
  • 1
    Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi May 27 '20 at 08:55

3 Answers3

1

You don't create your own promise (that's the explicit promise construction antipattern); instead, chain the existing promises together and return the result.

Here's one way you do that, see *** comments:

sentTest: (message) => {
    let mongoRecord = null;
    let asResponse;
    // *** Return the result of the chain
    return getMongoField('terminals', {'attributes.XYZ': 'ABC'})
    .then(function (docs) {
        // *** Return the promise for the next operation
        return ts.sendFirstMessage(docs.attributes.sno, docs, docs.attributes.value)
            .then(() => {
                // *** Return the promise for the next operation
                // This has to be nested because it uses `docs`
                return ts.SendSecondMessage(docs.attributes.sno, 'Test', docs, message);
            });
    })
},

or

sentTest: (message) => {
    let asResponse;
    // *** Return the result of the chain
    return getMongoField('terminals', {'attributes.XYZ': 'ABC'})
    .then(docs => {
        // *** Return the promise for the next operation
        return ts.sendFirstMessage(docs.attributes.sno, docs, docs.attributes.value)
            // *** Settle the promise from `then` with `docs` so the next handler can see it
            .then(() => docs);
    })
    .then(docs => {
        // *** Return the promise for the next operation
        return ts.SendSecondMessage(docs.attributes.sno, 'Test', docs, message);
    });
},
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you. I followed your first approach and I can see the code executes in the same order it is written. I have one more question T.J, lets consider I have two asynchronous function A and B, A call function B which intern calls function C with a callback. Now the problem is, as soon the function A calls B, B return a promise resolved but there are some action pending in function C. if you could help me understand , it would be great and helpful. thanks prashan I come from java world so everything is greek and latin to me. – Prashanna Narayanasamy May 27 '20 at 14:21
  • @PrashannaNarayanasamy - I'm afraid I don't quite understand the scenario you're talking about. If you're mixing promises with older style asynchronous callback APIs, usually your best bet is to do a promise wrapper around the old-style API. Then you can chain the promises to get things happening in the order you want without having to work in two different worlds. :-) – T.J. Crowder May 27 '20 at 14:32
  • Thank T.J you are correct I calling some functions which are written with callbacks, I will try creating a promise wrapper around the old one and see if that works. Thanks once again. – Prashanna Narayanasamy May 27 '20 at 14:35
  • @PrashannaNarayanasamy - [This question's answers](http://stackoverflow.com/questions/22707475/how-to-make-a-promise-from-settimeout/22707551#22707551) should help. :-) Happy coding! – T.J. Crowder May 27 '20 at 14:40
0

You don't need to introduce await inside promise. Because async function is functions that return promise already.

https://codesandbox.io/s/confident-banzai-24khs?file=/src/index.js

const obj = {
  sentTest: async message => {
    console.info("Before ", mongoRecord);
    mongoRecord = await getMongoField("terminals", { "attributes.XYZ": "ABC" });
    console.info("After", mongoRecord);

    // probably it needs await too. otherwise it will be a sideeffect
    // which may be evaluated after parent fucntion already return something.
    await ts.sendFirstMessage(
      mongoRecord.attributes.sno,
      mongoRecord,
      mongoRecord.attributes.value
    );


    // By the way you can't access `docs` variable here anyway
    return ts.SendSecondMessage(docs.attributes.sno, "Test", docs, message);
  }
};

heleg
  • 241
  • 3
  • 12
0

can introduce await inside promise?

You could, but there is no point in having it inside a Promise (see the link in T.J. Crowder's answer). You do not need an explicit Promise if you are already dealing with one.

See below for a way to write your code with async/await:

sentTest: async (message) => {
    let docs = await getMongoField('terminals', {'attributes.XYZ': 'ABC'});
    await ts.sendFirstMessage(docs.attributes.sno, docs, docs.attributes.value);
    return ts.SendSecondMessage(docs.attributes.sno, 'Test', docs, message);
},

Then call it like await something.sendTest(message).

str
  • 42,689
  • 17
  • 109
  • 127