Skip to main content
Used a more direct cross reference (as user names can change at any time).
Source Link
Peter Mortensen
  • 31.6k
  • 22
  • 109
  • 132

Felix Kling did a fine jobFelix Kling did a fine job writing an answer for people using jQuery with callbacks for Ajax. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

Felix Kling did a fine job writing an answer for people using jQuery with callbacks for Ajax. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

Felix Kling did a fine job writing an answer for people using jQuery with callbacks for Ajax. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

Adopted for CommonMark (as a result, the diff looks more extensive than it really is - use view "Side-by-side markdown" to compare).
Source Link
Peter Mortensen
  • 31.6k
  • 22
  • 109
  • 132

##If you're using promises, this answer is for you.

If you're using promises, this answer is for you.

##The core issue

The core issue

###Quick recap on promises

Quick recap on promises

###With promises

With promises

###Applying this

Applying this

##ES2015 (ES6)

ES2015 (ES6)

##ES2016 (ES7)

ES2016 (ES7)

##If you're using promises, this answer is for you.

##The core issue

###Quick recap on promises

###With promises

###Applying this

##ES2015 (ES6)

##ES2016 (ES7)

If you're using promises, this answer is for you.

The core issue

Quick recap on promises

With promises

Applying this

ES2015 (ES6)

ES2016 (ES7)

Active reading [<en.wikipedia.org/wiki/Sentence_clause_structure#Run-on_sentences> <en.wikipedia.org/wiki/Ember.js> <en.wikipedia.org/wiki/Backbone.js> <en.wikipedia.org/wiki/Node.js> <en.wikipedia.org/wiki/Ajax_%28programming%29> <en.wiktionary.org/wiki/let%27s#Etymology>].
Source Link
Peter Mortensen
  • 31.6k
  • 22
  • 109
  • 132

#If##If you're using promises, this answer is for you.

This means AngularJS, jQuery (with deferred), native XHR'sXHR's replacement (fetch), EmberJSEmber.js, BackboneJS'sBackbone.js's save or any nodeNode.js library that returns promises.

function foo() {
    var data;
    // orOr $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // result'result' is always undefined no matter what.

Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAXAjax. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

#The##The core issue

The JavaScript concurrency model in the browser and on the server with NodeJSNode.js/io.js is asynchronous and reactive.

Here is a simple analogy for the issue:   

    function getFive(){
        var data;
        setTimeout(function(){ // setSet a timer for one second in the future
           data = 5; // afterAfter a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second, but by that time it is irrelevant to the returned value.

Since the operation did not happen yet (AJAXAjax, server call, IOI/O, and timer) you're returning the value before the request got the chance to tell your code what that value is.

#Quick###Quick recap on promises

A Promise is a value over time. Promises have state, they. They start as pending with no value and can settle to:

A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAXAjax replacement fetch or jQuery's $.get return promises.

With promises

###With promises

function delay(ms){ // takesTakes amount of milliseconds
    // returnsReturns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // whenWhen the time is up,
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

Now, after we converted setTimeoutconverted setTimeout to use promises, we can use then to make it count:

function delay(ms){ // takesTakes amount of milliseconds
  // returnsReturns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // whenWhen the time is up,
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // we'reWe're RETURNING the promise,. rememberRemember, a promise is a wrapper over our value
  return delay(100).then(function(){ // whenWhen the promise is ready,
      return 5; // return the value 5,. promisesPromises are all about return values
  })
}
// weWe _have_ to wrap it like this in the call site, and we can't access the plain value
getFive().then(function(five){ 
   document.body.innerHTML = five;
});
function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // processProcess it inside the `then`
    });
}

foo().then(function(response){
    // accessAccess the value inside the `then`
})

So this works just as well. We've learned we can't return values from already asynchronous calls, but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.

#ES2015##ES2015 (ES6)

function* foo(){ // noticeNotice the star,. thisThis is ES6, so new browsers/node/, Nodes.js, and io.js only
    yield 1;
    yield 2;
    while(true) yield 3;
}

Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility, there is one particular interesting case.

This somewhat a tricky, but very powerful trick letslet’s us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing. Writing one is a short few lines of code, but it is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // noticeNotice the yield
    // The code here only executes _after_ the request is done
    return data.json(); // data'data' is defined
});
var main = coroutine(function*(){
   var bar = yield foo(); // waitWait our earlier coroutine,. itIt returns a promise
   // The server call is done here, and the code below executes when done
   var baz = yield fetch("/api/users/"+bar" + bar.userid); // dependsDepends on foo's result
   console.log(baz); // runsRuns after both requests are done
});
main();

#ES2016##ES2016 (ES7)

In ES7, this is further standardized, there. There are several proposals right now, but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:

async function foo(){
    var data = await fetch("/echo/json"); // noticeNotice the await
    // code here only executes _after_ the request is done
    return data.json(); // data'data' is defined
}

#If you're using promises, this answer is for you.

This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), EmberJS, BackboneJS's save or any node library that returns promises.

function foo() {
    var data;
    // or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // result is always undefined no matter what.

Felix Kling did a fine job writing an answer for people using jQuery with callbacks for AJAX. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

#The core issue

The JavaScript concurrency model in the browser and on the server with NodeJS/io.js is asynchronous and reactive.

Here is a simple analogy for the issue:  

    function getFive(){
        var data;
        setTimeout(function(){ // set a timer for one second in the future
           data = 5; // after a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second but by that time it is irrelevant to the returned value.

Since the operation did not happen yet (AJAX, server call, IO, timer) you're returning the value before the request got the chance to tell your code what that value is.

#Quick recap on promises

A Promise is a value over time. Promises have state, they start as pending with no value and can settle to:

A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern AJAX replacement fetch or jQuery's $.get return promises.

With promises

function delay(ms){ // takes amount of milliseconds
    // returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // when the time is up
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

Now, after we converted setTimeout to use promises, we can use then to make it count:

function delay(ms){ // takes amount of milliseconds
  // returns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // when the time is up
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // we're RETURNING the promise, remember, a promise is a wrapper over our value
  return delay(100).then(function(){ // when the promise is ready
      return 5; // return the value 5, promises are all about return values
  })
}
// we _have_ to wrap it like this in the call site, we can't access the plain value
getFive().then(function(five){ 
   document.body.innerHTML = five;
});
function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // process it inside the `then`
    });
}

foo().then(function(response){
    // access the value inside the `then`
})

So this works just as well. We've learned we can't return values from already asynchronous calls but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.

#ES2015 (ES6)

function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
    yield 1;
    yield 2;
    while(true) yield 3;
}

Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility there is one particular interesting case.

This somewhat tricky but very powerful trick lets us write asynchronous code in a synchronous manner. There are several "runners" that do this for you, writing one is a short few lines of code but is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // notice the yield
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
});
var main = coroutine(function*(){
   var bar = yield foo(); // wait our earlier coroutine, it returns a promise
   // server call done here, code below executes when done
   var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
   console.log(baz); // runs after both requests done
});
main();

#ES2016 (ES7)

In ES7, this is further standardized, there are several proposals right now but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:

async function foo(){
    var data = await fetch("/echo/json"); // notice the await
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
}

##If you're using promises, this answer is for you.

This means AngularJS, jQuery (with deferred), native XHR's replacement (fetch), Ember.js, Backbone.js's save or any Node.js library that returns promises.

function foo() {
    var data;
    // Or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // 'result' is always undefined no matter what.

Felix Kling did a fine job writing an answer for people using jQuery with callbacks for Ajax. I have an answer for native XHR. This answer is for generic usage of promises either on the frontend or backend.

##The core issue

The JavaScript concurrency model in the browser and on the server with Node.js/io.js is asynchronous and reactive.

Here is a simple analogy for the issue: 

    function getFive(){
        var data;
        setTimeout(function(){ // Set a timer for one second in the future
           data = 5; // After a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

The value of data is undefined since the data = 5 part has not executed yet. It will likely execute in a second, but by that time it is irrelevant to the returned value.

Since the operation did not happen yet (Ajax, server call, I/O, and timer) you're returning the value before the request got the chance to tell your code what that value is.

###Quick recap on promises

A Promise is a value over time. Promises have state. They start as pending with no value and can settle to:

A promise can only change states once after which it will always stay at the same state forever. You can attach then handlers to promises to extract their value and handle errors. then handlers allow chaining of calls. Promises are created by using APIs that return them. For example, the more modern Ajax replacement fetch or jQuery's $.get return promises.

###With promises

function delay(ms){ // Takes amount of milliseconds
    // Returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // When the time is up,
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

Now, after we converted setTimeout to use promises, we can use then to make it count:

function delay(ms){ // Takes amount of milliseconds
  // Returns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // When the time is up,
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // We're RETURNING the promise. Remember, a promise is a wrapper over our value
  return delay(100).then(function(){ // When the promise is ready,
      return 5; // return the value 5. Promises are all about return values
  })
}
// We _have_ to wrap it like this in the call site, and we can't access the plain value
getFive().then(function(five){
   document.body.innerHTML = five;
});
function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // Process it inside the `then`
    });
}

foo().then(function(response){
    // Access the value inside the `then`
})

So this works just as well. We've learned we can't return values from already asynchronous calls, but we can use promises and chain them to perform processing. We now know how to return the response from an asynchronous call.

##ES2015 (ES6)

function* foo(){ // Notice the star. This is ES6, so new browsers, Nodes.js, and io.js only
    yield 1;
    yield 2;
    while(true) yield 3;
}

Is a function that returns an iterator over the sequence 1,2,3,3,3,3,.... which can be iterated. While this is interesting on its own and opens room for a lot of possibility, there is one particular interesting case.

This somewhat a tricky, but very powerful trick let’s us write asynchronous code in a synchronous manner. There are several "runners" that do this for you. Writing one is a short few lines of code, but it is beyond the scope of this answer. I'll be using Bluebird's Promise.coroutine here, but there are other wrappers like co or Q.async.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // Notice the yield
    // The code here only executes _after_ the request is done
    return data.json(); // 'data' is defined
});
var main = coroutine(function*(){
   var bar = yield foo(); // Wait our earlier coroutine. It returns a promise
   // The server call is done here, and the code below executes when done
   var baz = yield fetch("/api/users/" + bar.userid); // Depends on foo's result
   console.log(baz); // Runs after both requests are done
});
main();

##ES2016 (ES7)

In ES7, this is further standardized. There are several proposals right now, but in all of them you can await promise. This is just "sugar" (nicer syntax) for the ES6 proposal above by adding the async and await keywords. Making the above example:

async function foo(){
    var data = await fetch("/echo/json"); // Notice the await
    // code here only executes _after_ the request is done
    return data.json(); // 'data' is defined
}
Post Undeleted by Benjamin Gruenbaum
Post Deleted by Benjamin Gruenbaum
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link
URL Rewriter Bot
URL Rewriter Bot
Loading
Florian can be such a tool sometimes http://chat.stackoverflow.com/transcript/message/23265427#23265427
Source Link
Benjamin Gruenbaum
  • 275.3k
  • 89
  • 515
  • 512
Loading
added 153 characters in body
Source Link
Benjamin Gruenbaum
  • 275.3k
  • 89
  • 515
  • 512
Loading
added 125 characters in body
Source Link
Benjamin Gruenbaum
  • 275.3k
  • 89
  • 515
  • 512
Loading
Source Link
Benjamin Gruenbaum
  • 275.3k
  • 89
  • 515
  • 512
Loading