0

I have read that Async function implicitly return a promise which is resolved by the return. Is there a way to get that promise returned by Async function so that we could resolve it ourself ?

I have a use case where i call an api which accepts a function which will be called asynchronously.

/**
 * 
 * @param {Array} keys - list of keys to get values
 */
let getStorageValues = async (keys) => {
    // chrome.storage.sync.get accepts second argument which is called asynchronously. 
    chrome.storage.sync.get(keys, (values) => {
        if (values) {
            return values;
        } else {
            return new Error('throw')
        }
    })

}

Instead i would want something like

let getStorageValues = async (keys) => {
    let AsyncPromise = Async Function Promise.
    chrome.storage.sync.get(keys, (values) => {
        if (values) {
            AsyncPromise.resolve(values);
        } else {
            AsyncPromise.reject(new Error('throw'))
        }
    })

}

If i could get access to the Promise returned by Async function i could use that to resolve the values variable used inside chrome.storage.sync.get

AnandShiva
  • 906
  • 11
  • 22
  • you need to add more explanation. Where is **that Async** function? Where do you call it? Probably you don't need to see the promise. If you tell your purpose more clearly, I could say more. – canbax Jan 31 '20 at 07:05
  • `Is there a way to get that promise returned by Async function` by invoking that function? – AZ_ Jan 31 '20 at 07:06
  • `chrome.storage.sync.get` doesn't return a promise. You will either need to wrap it in a promise and return that, or use the callback. Just putting it in an async function doesn't help you. – Mark Jan 31 '20 at 07:07
  • 1
    Does this answer your question? [How do I use Promise.all() with chrome.storage()?](https://stackoverflow.com/questions/49847904/how-do-i-use-promise-all-with-chrome-storage) – AZ_ Jan 31 '20 at 07:13
  • 1
    You are not using `await` anywhere in your function. Why mark it with `async`? – slebetman Jan 31 '20 at 07:13
  • @AZ_ thanks for that question. that is how my code is currently running - as a workaround. but it doesn't look clean. – AnandShiva Feb 01 '20 at 15:17
  • @slebetman I would like to use await but can't since chrome.store.sync.get accepts a call back and not a promise. So i thought Async implicitly returns a promise why not utilise it instead of create another promise wrapper and using it ? – AnandShiva Feb 01 '20 at 15:18
  • @AnandShiva Async implicitly wraps return values in a promise but it does not have the ability to convert callbacks into promises. For that you need to use `new Promise()`. The **only** reason to mark a function with the `async` keyword is to enable the use of `await`. That's why it's called `async/await`. Other than using `await` the `async` keyword does nothing else – slebetman Feb 01 '20 at 16:07

1 Answers1

1

To get something similar to what you think you want (ie. exporting resolve and reject callbacks) you will need to do something like this:

let getStorageValues = (keys) => { // Note: no async keyword because it is useless
    let resolve;
    let reject;

    let AsyncPromise = new Promise((a,b) => {
        resolve = a;
        reject = b;
    });

    chrome.storage.sync.get(keys, (values) => {
        if (values) {
            resolve(values);
        } else {
            reject(new Error('throw'))
        }
    })

    return AsyncPromise;
}

But this is obviously much more verbose than the usual:

let getStorageValues = (keys) => { // Note: no async keyword because it is useless
    return new Promise((resolve,reject) => {
        chrome.storage.sync.get(keys, (values) => {
            if (values) {
                resolve(values);
            } else {
                reject(new Error('throw'));
            }
        });
    }
}

On node.js you may also be able to massage your code to be able to utilize util.promisify:

const util = require('util');

let getStorageValues = util.promisify((keys,errorFirstCallback) => {
    chrome.storage.sync.get(keys, (values) => {
        if (values) {
            errorFirstCallback(null,values);
        } else {
            errorFirstCallback(new Error('throw'));
        }
    });
});

Unfortunately the async keyword cannot be made to do what you think you want.

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • I think `util.promisify` can promisify only functions that accept an `error first callback`? – AZ_ Feb 01 '20 at 17:16
  • @AZ_ Yes, see my example code for how to convert the OP's code to error first callback. It's already in my answer – slebetman Feb 01 '20 at 17:18
  • @AZ_ For clarity I'll change the name of the `callback` parameter - I'm not changing anything else – slebetman Feb 01 '20 at 17:18
  • oh, I didn't see the wrapper callback in the first go, but now its more clear why a wrapper callback is required. – AZ_ Feb 01 '20 at 17:23