-2

I have two third party functions which I cannot change:

One functions expects a callback that possibly could return a new data, not promise. The other function returns the new data in promise. How to connect these two functions together?

I have looked at various examples, they always suggests to use Promise.then or async await, but I don't see it applicable inside a callback.

// One 3rd party API
runExternalTransaction(callback: (currentData: any) => unknown) {
// Some 3rd party code.
}

// The other 3rd party API
getNewData(): Promise<any> {
// Some 3rd party code to get data from data storage.
}

// An attempt to put these functions together
runExternalTransaction(currentData => {
    if (!currentData) { // Only return new data if current data not available.
        getNewData().then(newData => ...);
        // How to return new data?
        return ...;
    }
});
appsofteng
  • 152
  • 5
  • To convert a callback function to a promise you need to use the Promise constructor pattern, -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise – Keith Nov 08 '22 at 12:59
  • 1
    Does this answer your question? [How do I convert an existing callback API to promises?](https://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises) – rveerd Nov 08 '22 at 13:18
  • @Keith Thanks, I have seen the Promise constructor pattern, but I don't see how to use it for my problem, maybe I am missing something, could you please apply it to my example? – appsofteng Nov 08 '22 at 13:27
  • I don't see any async code in your example,.. aka. The function you said expects a callback. – Keith Nov 08 '22 at 13:28
  • @Keith The async part is the other third party function getNewData() which returns a promise. I need to get the data from the promise and return them from the callback. – appsofteng Nov 08 '22 at 13:37
  • `getNewData().then(newData => /* new data here */)` btw. `runExternalTransaction` will need to either use a callback or return a promise if your expecting the caller to get the return value. – Keith Nov 08 '22 at 13:39
  • runExternalTransaction((currentData: any) => { if (!currentData) { getNewData().then(newData => /* new data here */); // how to return the new data? } }); – appsofteng Nov 08 '22 at 13:42

1 Answers1

0

You need to promisify the first one, and then chain the promise you get with the second promise:

// Promisify the first 3rd party API
const promiseExternalTransaction = () => new Promise(runExternalTransaction);

promiseExternalTransaction().then(currentData => {
    return currentData && getNewData();
}).then(newData => {
    if (newData) {
       // Do something with new data...
    }
});

Note that the promisification looks very simple here, because the callback is the first argument that is passed to runExternalTransaction, and that callback gets the result as first argument. If any of these two aspects is different, you need a bit more code to define promiseExternalTransaction.

It should be clear that you need to process the asynchronous result in a then callback (or following an await in an async function), and cannot expect the result to be returned to synchronously running code, as that would be mean you would get a future result now.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
trincot
  • 317,000
  • 35
  • 244
  • 286