0

I have some bussiness logic function to call , which has a logic that must use HttpGet , And I have to wait until it returns the result to contiune ,if i use jquery's ajax can simple do it all , do not know whether the Observable also has similar way?


I hope the resut is :

  • John
  • Andy

but now the result is only show Andy :(


function main(){  
/*
  I have more than 70 sharing rules to deal with different Logic
  (e.g. getAge , getSomthing...), in order to simplify the problem ,
  I only list two rules as a demonstration
*/
  methods = [
    getNameFromServer,
    getSomeOneName
  ];
  
  const result = [];  
  methods.forEach(method => {
    method(result);
  })
  
  console.log(result);
}

function getNameFromServer(result){
  Rx.Observable.of('John')
    .delay(1000)
    .subscribe(name => {   
      console.log('now async get name , but I need it will be sync')
      result.push(name)
    });
  
  // can I use sync Ajax like jquery's code?
  // $.ajax({ 
  //          ... ,
  //          async: false 
  //        })
  //  .done(response => result.push(response.xxx))
}

function getSomeOneName(result){
  result.push('Andy');
}


// execute
main();
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.js"></script>
</head>
<body>
</body>
</html>
Chunbin Li
  • 2,196
  • 1
  • 17
  • 31
  • Instead of `async: false` -> [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Andreas Jun 21 '17 at 15:51
  • your console.log(result); is running before the observable adds John to the result array. console.log(result) after result.push(name) within your observable – LLai Jun 21 '17 at 15:55
  • Because the observable finished after console.log(result); – aimprogman Jun 21 '17 at 15:58
  • thanks , I know Observable will end after console.log , but if I use jquery ajax and set async to false , it will execute before console.log and I get result I want : [ John , Andy ] – Chunbin Li Jun 21 '17 at 23:36
  • I would recommend against synchronous http requests, as this blocks all of your js from executing while it waits for the http request to finish. I would leave the observable as asynchronous and move your result.push('Andy') after your result.push(name) in your observable success callback. This would give you your desired ['John', 'Andy'] – LLai Jun 22 '17 at 04:42
  • @LLai I agree with your idea , because I think so , but the reason Why I would do that in reailty , the whole site I have more than 70 sharing rules to deal with different logic( e.g. getAge, getSomething... ) ,so I think to rewrite every rule as a Observable , the risk is bit big , I would prefer to be the smallest changes to comlete this matter – Chunbin Li Jun 22 '17 at 23:51

1 Answers1

1

In any modern browser you can use async/await to get a synchronous behavior. You must:

  • Declare your main as async
  • Replace the forEach with for..of (callbacks don't work well with await)
  • Convert your Observable to Promise to make it awaitable, then return it
  • Replace subscribe with do. You still get the side effects but do returns the observable so you can immediately chain toPromise. The observer is automatically subscribed by toPromise

Code would be:

async function main(){  

      methods = [
        getNameFromServer,
        getSomeOneName
      ];
      
      const result = [];
      for (let method of methods) {
        await method(result);
      }
      console.log(result);
    }
    
    function getNameFromServer(result){
      return Rx.Observable.of('John')
        .delay(1000)
        .do(name => {   
          console.log('now async get name , but I need it will be sync')
          result.push(name)
        })
        .toPromise();
      
      // can I use sync Ajax like jquery's code?
      // $.ajax({ 
      //          ... ,
      //          async: false 
      //        })
      //  .done(response => result.push(response.xxx))
    }
    
    function getSomeOneName(result){
      result.push('Andy');
    }
    
    
    // execute
    main();
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.js"></script>
</head>
<body>
</body>
</html>
Chunbin Li
  • 2,196
  • 1
  • 17
  • 31