0

I am coming at this question from a standpoint of having an extremely minimal understanding of the subject matter and I am trying to figure out and understand what is happening.

I read through the article at How do I return the response from an asynchronous call? but I cannot understand it.

However, based on my read, it would seem that the section entitled "If you're not using jQuery in your code, this answer is for you" is the section that deals with the structure I am using. However because the material referenced in the example is so different from mine, I simply cannot follow or understand it enough to be able to effectively apply it to my code.

I also read through a lot of the other articles about returning values from promise chains, but I cannot fully follow or understand them either due to my pre-beginner level status in terms of asynchronous javascript and promises.

I am hoping someone can explain in the simplest of ways and help me understand how to apply the material in the section entitled "If you're not using jQuery in your code, this answer is for you" from How do I return the response from an asynchronous call? to my code.

I have a function and inside of the function there is an asynchronous piece of javascript.

I updated my code to this:

function LF(action, key, value){
  var ectcb = localforage.createInstance({name: "ectcb"});
    return ectcb.defineDriver(window.cordovaSQLiteDriver).then(function() {
    return ectcb.setDriver([
    window.cordovaSQLiteDriver._driver,
    ectcb.INDEXEDDB,
    ectcb.WEBSQL,
    ectcb.LOCALSTORAGE
    ]);
      }).then(function() {
        if (ectcb.driver().toString() = 'cordovaSQLiteDriver'){
          if (action = 'save'){ectcb.setItem(key, value); return true;} 
          else if (action = 'load'){ectcb.getItem(key, value); return true;}
          else {return false;}
          }
        else {return false;}
      }).catch(function(err) {
        return false;     
      });
    };

It was originally the code directly below

function LF(action, key, value) {
  var ectcb = localforage.createInstance({
    name: "ectcb"
  });
  var thePromiseResult = ectcb.defineDriver(window.cordovaSQLiteDriver).then(function() {
    return ectcb.setDriver([
      window.cordovaSQLiteDriver._driver,
      ectcb.INDEXEDDB,
      ectcb.WEBSQL,
      ectcb.LOCALSTORAGE
    ]);
  }).then(function() {
    if (ectcb.driver().toString() = 'cordovaSQLiteDriver') {
      if (action = 'save') {
        return ectcb.setItem(key, value);
      } else if (action = 'load') {
        return ectcb.getItem(key, value);
      } else {
        thePromiseResult = 1;
      }
    } else {
      thePromiseResult = 1;
    }
  }).catch(function(err) {});

  if (thePromiseResult = 1) {
    return false;
  } else {
    return true;
  }
};

I have a variable named thePromiseResult set to the async code.

I am trying to comprehend how I can cause a specific value to be set to thePromiseResult based on the if/else logic shown within the code.

Ultimately, something will be calling LF('save','thekey','the value') and I need to return to that "something" the value of true or false.

I am hoping someone can explain how i can alter this code to achieve what I need to do, and explain it in a very simple for-dummies way so I can truly understand what is happening.

I think that setting "thePromiseResult = 1" inside the .then is probably not setting it globally and just setting it inside the .then with the desired value.

I tried to look at the other posts on this topic and I cannot grasp the concepts using the various examples they show.

My goal is to have code on a different page that says

var result = LF('fake','myKey','myValue')

if (result = false){alert("Operation Failed");
else if (result = true){alert("Operation Successful");  

I am trying to break the code up so that it mirrors what is being done under 2. Restructure code where it talks about letting your function accept a call back. However, because the code used in that example is so different than what I have, I am just not knowledgeable enough to follow what is being described.

I am hoping someone can take a kindergarten coder approach to help me translate the concepts so that it is more clear how it can be applied to my code.

ACE
  • 33
  • 6
  • `=` is assignment, not comparison. `return` each Promise so that the consumer of `LF` can call `.then` on the call, and from that you can get the final resolve value – CertainPerformance Mar 17 '19 at 05:41
  • I am coming at this question from an extreme novice understanding of the subject matter & am trying to figure out and understand what is happening. I read through the article at "How do I return the response from an asynchronous call?" but I cannot understand it. It seems that the section titled "If you're not using jQuery in your code, this answer is for you" is the section that is most similar to mine. But because the code there is so different from mine, I simply cannot follow or understand it enough to be able to effectively apply it to my code. – ACE Mar 17 '19 at 07:26
  • You need to return the Promise. Your `var thePromiseResult =` means `thePromiseResult` is not the result, it is the Promise itself; return it, and don't try to reassign it, and inside the `.then`, `return` the value you want the consumer to get (eg `return 1`), and then the caller of LF will have a Promise that (might) resolve to `1` (or whatever else you want to resolve it to) – CertainPerformance Mar 17 '19 at 07:28
  • When you say "return it" -- that's what is totally unclear. Where exactly are you suggesting the return goes? Are you saying I should write it as "var thePromiseResult = return ectcb.defineDriver(window.cordovaSQLiteDriver).then"? – ACE Mar 17 '19 at 07:32
  • Secondly, the value I am trying to return is in 2 or 3 .then(s) in and I need to return a different value based on logic that I insert that responds to data passed in by the calling fuction-- so thats part of my problem. I cannot see how to apply the material in the examples from that other article to the 3rd .then. Sorry for being so slow. I have never dealt with asynchronous code before and am trying to both understand what's happening and get something done while I do so. I am sort of picking up the concepts, but I am struggling in application. – ACE Mar 17 '19 at 07:35
  • Your `thePromiseResult` is not the result of the Promise - it is the Promise itself. Return that Promise object so that the caller of `LF` can use it. You might ditch that variable entirely: `return ectcb.defineDriver(...`, and then inside the last `.then`, `return` whatever you want the caller to have – CertainPerformance Mar 17 '19 at 07:38
  • I tried editing my code in the original post (see above), but when I return it, am still getting [object Promise] for the value as opposed to true or false, which is ideally what i want. – ACE Mar 17 '19 at 07:50
  • You cannot get data that is retrieved asynchronously as if it was synchronous. Like I said, you have to call `.then` on the result of `LF` – CertainPerformance Mar 17 '19 at 07:51
  • So something like function LF(action, key, value).then(function(action,key,value){the rest of the stuff – ACE Mar 17 '19 at 13:59
  • Am I understanding that correctly? – ACE Mar 17 '19 at 14:00
  • I do not clearly understand the statement “you have to call .then on the result of LF” – ACE Mar 17 '19 at 14:02

1 Answers1

0

If I understand your question, it seems like you are trying to make your promise return a non-promise result. Let's say:

// you want "result" to be 2 here
var result = somePromise
  .then(asyncTwo => asyncTwo) // lets say the promise resolved with 2

result // still a promise, but you want it to be 2

This is a misunderstanding of how and why promises are used. When dealing with asynchronous code, the callbacks always resolve after your synchronous code has executed. This means that result can never be set to 2 where you want it to be.

This might help drive the point home:

console.log('synchronous code start')
var result

var somePromise = new Promise((resolve) => {
  setTimeout(() => {
    resolve(2)
  }, 0)
})

somePromise.then(asyncTwo => {
  console.log('somePromise resolves with 2')
  result = asyncTwo // set result to two
})

console.log('this code is synchronous so result still equals ', result)

setTimeout(() => {
  console.log('sometime later result may equal ', result)
  console.log('but your synchronous code has already finished so this is unhelpful!') 
}, 500)

console.log('synchronous code finished')

The answer is to embrace the Promise pattern so you can deal with asynchronous code in a logical way. Instead of trying to lift your asynchronous result into your synchronous code (which is not possible by the way), chain additional then / catch to apply additional logic to the async result.

// lets mock out an example of what you might get:

function asyncOneOrTwo () {
  // one or two randomly
  let oneOrTwo = Math.floor(Math.random() * 2) + 1
  return Promise.resolve(oneOrTwo)
}

function LF () {
  return asyncOneOrTwo()
    .then(oneOrTwo => {
      // you can reject with an error message instead if that's your preference
      if (oneOrTwo === 1) return Promise.reject(oneOrTwo)
      else return Promise.resolve(oneOrTwo)
    })
}

// in another file
// chain `then` or `catch` to do additional error handling
LF()
  .then(res => {
    console.log('success we got: ', res)
  })
  .catch(err => {
    console.log('fail we got: ', err)
  })
Damon
  • 4,216
  • 2
  • 17
  • 27
  • Sounds like you are on to something. Let me try and digest what you have posted and I will reply with a super basic version of code once I digest it -- with the hope that i will understand it enough that my basic code repost is correct. Once that happens, I should be able to extrapolate that into my larger piece of code. My apologies for being slow/difficult to comprehend.. this is the first time I am working with async code so I have to digest a lot. I'll post back once I digest and refactor a simple example that makes sense to me. Hopefully I finally get it in my follow-up. Thanks much! – ACE Mar 17 '19 at 18:20
  • @ACE np. Run the first snippet if you need help understanding what's actually happening. The logs should give you a good idea of the fact that sync code always completes before async code, (even if the async code is something like a 0 second timeout). If you want an in depth understanding of why, read [this article](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop), however that might be more in depth than you need to go for now. – Damon Mar 17 '19 at 19:11