Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should synchronous code called by Promise .then create a new Promise

I've implemented some code, where asynchronous code is followed by some synchronous functions. For example:

function processSomeAsyncData() {
  asyncFuncCall()
    .then(syncFunction)
    .catch(error);
}

If I understand correctly then is also a Promise. Then, should I create a promise in the synchronous code as well?

function syncFunction() {
  const p = new Promise (function (resolve, reject) {
    //Do some sync stuff
    ...
    resolve(data);
  }
  return p;
}

If that isn't necessary, how do you reject the promise from the synchronous code if an error occurred?

like image 403
Jan Swart Avatar asked Aug 05 '16 19:08

Jan Swart


People also ask

Can a promise handle synchronous?

A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.

Does .then return a promise?

The then() method returns a Promise . It takes up to two arguments: callback functions for the success and failure cases of the Promise .

Is promise all synchronous or asynchronous?

Fulfillment. The returned promise is fulfilled with an array containing all the fulfilled values (including non-promise values) in the iterable passed as the argument. If an empty iterable is passed, then the promise returned by this method is fulfilled synchronously.

Are promises always asynchronous?

In testing I've found that JavaScript Promises are always asynchronous regardless of whether or not they contain any asynchronous functions in their chain. Here is some code that shows the order of operations in console.


Video Answer


2 Answers

You don't need to create a new promise explicitly. There is an easier way.

This example is contrived because it will never fail, but the point is that you don't have to create a promise and you don't have to return a resolve(val).

function syncFunction() {
  var j = "hi"
  if(j){
    return j;
  }
  return new Error('i am an error');
}

This will work:

asyncFunction()
  .then(syncFunction);

But if you did it the other way around:

syncFunction()
  .then(asyncFunction);

You would have to define your syncFunction as:

function syncFunction() {

  var j = "hi"
  return new Promise((resolve, reject) => {
    if(j){
      return resolve(j);
    }
    return reject('error');
  })  
}

Edit: To prove to all you non believers out there, give this guy a shot locally on your computer. Proves that you have these many options available to you. :)

var Promise = require('bluebird');


function b(h) {
    if(h){
        return h;
    }
    return Promise.resolve('hello from b');
}

function a(z) {
    return new Promise((resolve, reject)=> {
        if(z){return resolve(z)};
        return resolve('hello from a');
    })
}

a().then(b).then(x => console.log(x)).catch(e => console.log(e));
b().then(a).then(x => console.log(x)).catch(e => console.log(e));
like image 59
Patrick Motard Avatar answered Sep 27 '22 16:09

Patrick Motard


No. Synchronous functions may be called from synchronous code and should always fail synchronously! They need not conform to asynchronous callers in any way. If an error occurs just throw an error. Try it:

var asyncFuncCall = () => Promise.resolve();

function syncFunction() {
  throw new Error("Fail");
}

asyncFuncCall()
  .then(syncFunction)
  .catch(e => console.log("Caught: " + e.message));

This works because an exception thrown by a function passed to a .then is converted to a rejection of the promise it is supposed to return.

Additionally, any value returned by a function passed to a .then is converted to a promise resolved with that value. The promise code calling the function takes care of this.

This lets you mix synchronous and asynchronous code without problems:

asyncFuncCallOne()
  .then(() => {
    var x = syncFunction();
    return asyncFuncCallTwo(x);
  })
  .catch(e => console.log(e.message));
like image 40
jib Avatar answered Sep 27 '22 17:09

jib