2

I need to return a promise which contains an object. I have tried this but I'm not sure if this is the correct way?

export const getCurrentLocation = async () => {
  const currentLoc = {
    code: null,
    position: null,
    watchId: null,
  };

  const promise = new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        currentLoc.code = 200;
        currentLoc.position = position;

        resolve(currentLoc);
      },
      (error) => {
        console.log('Postion==err===>', error);
        currentLoc.code = 400;
        reject(currentLoc);
      },
      {enableHighAccuracy: true, timeout: 20000, maximumAge: 1000},
    );
  }).then(
    new Promise((resolve, reject) => {
      const watchId = navigator.geolocation.watchPosition();
      currentLoc.watchId = watchId;
      resolve(currentLoc);
    }),
  );

  return promise;
};

Inside Promise block I have asynchronous function

Deepak
  • 31
  • 4
  • 2 issues your forgetting to return a promise, and the first resolve needs to be attached to the second promise, otherwise your resolving before you have even executed the second promise. – Keith Jul 16 '20 at 07:51
  • 5
    `return Promise.resolve(obj).then(obj => { obj.value1 = 'Deepak'; return obj; }).then(obj => { obj.value2 = 'JavaScript'; return obj; })` – Aluan Haddad Jul 16 '20 at 07:52
  • 2
    Why are you even returning a promise here? It's totally redundant? – Liam Jul 16 '20 at 07:53
  • Even though it's redundant, it would work with `() =>` added after `.then(` and before the second `new Promise` – CherryDT Jul 16 '20 at 07:57
  • @Liam because I want to access the obj with both value1 and value2 whenever I called the function. – Deepak Jul 16 '20 at 07:58
  • 3
    @Deepak but you don't need a Promise to do that. There is no asynchronous code here - you are overcomplicating the things, just do `obj.value1 = "Deepak"; obj.value2 = "JavaScript"`. Or even `return {value1: "Deepak", value2: "JavaScript"}` – VLAZ Jul 16 '20 at 08:00
  • maybe you can try using Promise.all() function – Moufeed Juboqji Jul 16 '20 at 08:02
  • @VLAZ this is the demo. Actually what will happen is Callback back will get called and inside the Callback function, value1 and value2 will be assigned. – Deepak Jul 16 '20 at 08:07
  • 1
    @Deepak callbacks are still synchronous. If you're going to use that in a promise chain, then *you still don't need promises* - the result would be lifted to a promise automatically. This seems more and more like [an XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – VLAZ Jul 16 '20 at 08:09
  • @VLAZ Callback I meant APIS call. We have to wait for the API response.then assign the value to obj. – Deepak Jul 16 '20 at 08:13
  • 1
    @Deepak `makeAjaxCall().then(obj => { obj.value1 = "Deepak"; obj.value2 = "JavaScript"; return obj; }).then(doMoreStuff)` - as I said, no need for promises. The result is automatically lifted. – VLAZ Jul 16 '20 at 08:14
  • It's becoming increasingly unclear what your trying to achieve here. Please re-word the question to be more clear. Basically I agree with all of VLAZ points. – Liam Jul 16 '20 at 08:16
  • @VLAZ Are you saying we cannot use callback inside Promise block. There are cases where results depend on the callback function inside Promise block. – Deepak Jul 16 '20 at 08:20
  • I'm saying that what you've shown here has no reason to use promises. You claim you need a function that returns a promise yet all you do is synchronous operations that don't need specific async handling. You later clarified this has to happen in some relation to a network call. Again, unless there is something you're not showing - no need for that, a normal synchronous function can and usually *should* be used as the `.then` callback. Wrapping stuff in more promises than needed just makes the code harder to read and has literally no benefit at all. – VLAZ Jul 16 '20 at 08:24
  • @Liam I have mentioned in the code block that inside Promise there is a callback function. But you guys saying don't use a callback function. It's like if I have a problem in fetch don't use fetch use Axios – Deepak Jul 16 '20 at 08:24
  • @Deepak callback functions *do not need to return a promise*. We've said that because it's true. It doesn't matter if it's within a Promise executor or not. `new Promise(res => callback(res))` will function perfectly fine when `callback` is synchronous instead of producing a promise. And since all promises flatten automatically type of the return value is completely irrelevant anyway - it will always be converted to a single level promise whether it was a plain value or a promise beforehand. – VLAZ Jul 16 '20 at 08:29
  • @VLAZ Thanks I got your point. But my callback is not synchronous it is asynchronous. That's why I mention APIs in my previous comments. Because APIs asynchronous – Deepak Jul 16 '20 at 08:44
  • Again, that shouldn't matter. If you have an async call you can chain a synchronous function as `then` and that's OK. That's the reason promises were made, in fact. I still don't see why you claim there is a need to produce a promise if there is no asynchronicity in simply assigning values. – VLAZ Jul 16 '20 at 08:54
  • @VLAZ I have reposted the question. So to get the value I call like this const loc = await getCurrentLocation() I hope I'm now clear. Please have a look. Thanks for your help. – Deepak Jul 16 '20 at 09:03
  • It's dead simple - as previously mentioned, no need for extra promises `new Promise ( /* same as above */).then(loc => { loc.watchId = navigator.geolocation.watchPosition(); return loc; } )`. The assignment is synchronous operation as is `.watchPosition()` and `then` automatically lifts the result to a promise anyway. – VLAZ Jul 16 '20 at 09:24
  • @VLAZ Thanks I understood now except that why I need to return loc if I'm returning the promise at end – Deepak Jul 16 '20 at 09:53
  • `.then` returns a new promise. The return result of the callback becomes the value the promise resolves with. – VLAZ Jul 16 '20 at 10:08
  • @VLAZ Understood now. Thanks for your patience and help – Deepak Jul 16 '20 at 15:53

1 Answers1

-2

You can use async/await:

const obj = {};
const populate = async() => {
  await (() => obj.value1 = 'Deepak')();
  await (() => obj.value2 = 'JavaScript')();
  console.log(obj);
};
populate();
Pingolin
  • 3,161
  • 6
  • 25
  • 40
  • 3
    What are you even awaiting? There is no promise in that code that needs to be awaited - you've introduced IIFEs which obscure things. – VLAZ Jul 16 '20 at 08:02
  • @VLAZ OP does the same w/ the Promises. – StefanN Jul 16 '20 at 08:04
  • 2
    @StefanN also, OP clearly struggles with Promises. Using `await` is not really an improvement but actively misleading to somebody who is already unfamiliar with the concept. – VLAZ Jul 16 '20 at 08:07
  • True. Introducing yet another technique doesn't add to that, but if you want to load data async I think it's cleaner and easier maintainable w/ async/await and that, IMHO, validates @Armel's answer. – StefanN Jul 16 '20 at 08:14
  • It's just to show another solution, there is nothing to be awaited in the question in the first place, it's a short example to use another structure to chain promises. The example I wrote could be better, but people tend to understand faster async/await than promises. – Pingolin Jul 16 '20 at 08:15
  • 1
    @StefanN *maybe* it's the right tool but it's shown incorrectly. That makes it the wrong answer for me. There is the whole conditional at the start, though. – VLAZ Jul 16 '20 at 08:16