Презентация - Promises

Asynchronous programming and promises, async / await, Web workers - JS Applications - ноември 2016

 

Материали от темата

Съдържание на документа

Asynchronous
Programming and Promises

Promises. Async / Await. Web Workers

SoftUni Team

Technical Trainers

Software University

http://softuni.bg

Promises

Promises

.then()

.catch()


Table of Contents

Asynchronous Programming

Promises in JS – Concepts

Promises with AJAX

Using Async / Await

Web Workers

2


3



sli.do
#promises

Have a Question?


Asynchronous Programming


5

Asynchronous programming deals with the needs to run several tasks (pieces of code) in parallel, in the same time









In JS the asynchronous programming is based on callbacks

You run a background task and pass a callback function

Asynchronous Programming in JS


6

Asynchronous Programming – Example

setTimeout(task1, 1000);

setTimeout(task2, 1500);

setTimeout(task3, 500);

console.log("All tasks started");

function task1() { console.log("task1 finished") }

function task2() { console.log("task2 finished") }

function task3() { console.log("task3 finished") }

All tasks started

task3 finished

task1 finished

task2 finished

All tasks run in parallel



3 tasks run in parallel and

will finish at different time


Promises in JS

Objects Holding Asynchronous Operations

Promises

.then()

.catch()


8

A promise is an object holding an asynchronous operation

A result which may be available now, or in the future, or never

Promises may be in one of these states:

Pending – operation still running (unfinished)

Fulfilled – operation finished (and the result is available)

Failed – operation is failed (and an error is available)

Promises in JS use the Promise object

What is a Promise?


9

JS Promises – Syntax

let p = new Promise(function(resolve, reject) {

  // Do an async task and then resolve or reject

  if (/* operation successful */)

    resolve('Success!');

  else /* operation failed */

    reject('Failure!');

});

p.then(function(result) { 

  /* process the result (when the promise is resolved) */ })

.catch(function(error) { 

  /* handle the error (when the promise is rejected) */ });


10

Promise.then() – Example

console.log('Before promise');

new Promise(function(resolve, reject) {

  setTimeout(function() { 

    resolve('done'); 

  }, 500);

})

.then(function(result) {

  console.log('Then returned: ' + result);

});

console.log('After promise');

Check your solution here: https://judge.softuni.bg/Contests/360

Before promise

After promise

Then returned: done

Resolved after 500 ms


11

Promise.catch() – Example

console.log('Before promise');

new Promise(function(resolve, reject) {

  setTimeout(function() { 

    reject('fail'); 

  }, 500);

})

.then(function(result) { console.log(result); })

.catch(function(error) { console.log(error); });

console.log('After promise');

Check your solution here: https://judge.softuni.bg/Contests/360

Before promise

After promise

fail

Rejected after 500 ms


12

JS Promises – Example – First Task

let p1 = new Promise(

  function(resolve, reject) {

    console.log("task1 started.");

    setTimeout(function() {

      resolve("task1 result");

      console.log("task1 finished.");

    }, 1000);

  }

);


13

JS Promises – Example – Second Task

let p2 = new Promise(

  function(resolve, reject) {

    console.log("task2 started.");

    setTimeout(function() {

      resolve("task2 result");

      console.log("task2 finished.");

    }, 1500);

  }

);


14

JS Promises – Example – Third Task

let p3 = new Promise(

  function(resolve, reject) {

    console.log("task3 started.");

    // reject('cannot execute task3');

    setTimeout(function() {

      resolve("task3 result");

      console.log("task3 finished.");

    }, 500);

  }

);


15

JS Promises – Example – Third Task

console.log("All tasks started.");

Promise.all([p1, p2, p3])

  .then(function(result) {

     console.log("All tasks finished.");

     console.log("Result: " + result.join(", "));

     // nonExistingFunction();

  })

  .catch(function(error) {

     console.log("Some of the tasks failed.");

     console.log("Error: " + error);

  });

Error in then() block will reject the promise

Check your solution here: https://judge.softuni.bg/Contests/360




Promises with jQuery AJAX

Promises

.then()

.catch()


17

Problem: Load GitHub Commits with AJAX

GitHub username:

<input type="text" id="username" value="nakov" /> <br>

Repo: <input type="text" id="repo" value="nakov.io.cin" />

<button onclick="loadCommits()">Load Commits</button>

<ul id="commits"></ul>

<script>

  function loadCommits() {

     // AJAX call … 

  }

</script>


18

Solution: Load GitHub Commits with AJAX

function loadCommits() {

  $("#commits").empty();

  let url = "https://api.github.com/repos/" +

    $("#username").val() + "/" +

    $("#repo").val() + "/commits";

  $.get(url)

    .then(displayCommits)

    .catch(displayError);

  function displayCommits(commits) { … }

  function displayError(err) { … }

}

jQuery AJAX methods return promises


19

Solution: Load GitHub Commits with AJAX (2)

function displayCommits(commits) {

  for (let commit of commits)

    $("#commits").append($("<li>").text(

       commit.commit.author.name + ": " +

       commit.commit.message

    ));

}

function displayError(err) {

  $("#commits").append($("<li>").text("Error: " +

    err.status + ' (' + err.statusText + ')'));

}

Check your solution here: https://judge.softuni.bg/Contests/360


20

Create a Kinvey app

Create user "peter" with password "p"

Create posts "Post1" and "Post2"

Create comments "Com1a" and "Com1b" for "Post1"

Create comments "Com2a", "Com2b" and "Com2c" for "Post2"

Write a JS app to display all posts and view selected post along with its comments

Problem: Blog (Posts with Comments)


21

Solution: Blog – Create a Kinvey App

Remember your app ID


22

Solution: Blog – Create User "peter"


23

Solution: Blog – Create the First Post

POST /appdata/kid_B15S6I9Zl/posts/ HTTP/1.1

Host: baas.kinvey.com

Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=

Content-Type: application/json



{ "title":"Post1", "body":"Post #1 body" }

{ "title": "Post1", "body": "Post #1 body", …,

  "_id": "582cde77209db9d9730bab03" }

Remember the post _id







Base64(user:pass)

Insert your Kinvey App ID here




24

Solution: Blog – Create the Comments

POST /appdata/kid_B15S6I9Zl/comments/ HTTP/1.1

Host: baas.kinvey.com

Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=

Content-Type: application/json



{ "text":"Com1a", "post_id":"582cde77209db9d9730bab03" }

POST /appdata/kid_B15S6I9Zl/comments/ HTTP/1.1

Host: baas.kinvey.com

Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=

Content-Type: application/json



{ "text":"Com2a", "post_id":"582cde77209db9d9730bab03" }

Use post _id from the previous request




25

Create the second post "Post2" + its 3 comments

The "posts" and "comments" collections should look like these:

Solution: Blog – Create the Second Post












26

Solution: Blog – HTML Code

<script src="jquery-3.1.1.min.js"></script>

<script src="blog.js"></script>



<h1>All Posts</h1>

<button id="btnLoadPosts">Load</button>

<select id="posts"></select>

<button id="btnViewPost">View</button>



<h1 id="post-title">Post Details</h1>

<ul id="post-body"></ul>

<h2>Comments</h2>

<ul id="post-comments"></ul>


27

Solution: Blog – JS Code

$(document).ready(function() {

  const kinveyAppId = "kid_B15S6I9Zl";

  const serviceUrl = "https://baas.kinvey.com/appdata/" + kinveyAppId;

  const kinveyUsername = "peter";

  const kinveyPassword = "p";

  const base64auth = btoa(kinveyUsername + ":" + kinveyPassword);

  const authHeaders = { "Authorization": "Basic " + base64auth };

  $("#btnLoadPosts").click(loadPostsClick);

  $("#btnViewPost").click(viewPostClick);

  function loadPostsClick() { … }

  function viewPostClick() { … }

  …

});


28

Solution: Blog – Load Posts

function loadPostsClick() {

  let loadPostsRequest = {

    url: serviceUrl + "/posts",

    headers: authHeaders,

  };

  $.ajax(loadPostsRequest)

    .then(displayPosts)

    .catch(displayError);

}


29

Solution: Blog – Display Posts as Options

function displayPosts(posts) {

  $("#posts").empty();

  for (let post of posts) {

    let option = $("<option>")

      .text(post.title)

      .val(post._id);

    $("#posts").append(option);

  }

}


30

Solution: Blog – Handle AJAX Errors

function displayError(err) {

  let errorDiv = $("<div>").text("Error: " +

    err.status + ' (' + err.statusText + ')');

  $(document.body).prepend(errorDiv);

  setTimeout(function() {

    $(errorDiv).fadeOut(function() {

      $(errorDiv).remove();

    });

  }, 3000);

}


31

Kinvey allows querying collections:

Solution: Blog – Load Post Comments Query

https://baas.kinvey.com/appdata/kid_B15S6I9Zl/comments?query={"post_id":"582cde77209db9d9730bab03"}


32

Solution: Blog – [View Post] Button Click

function viewPostClick() {

  let selectedPostId = $("#posts").val();

  if (!selectedPostId) return;

  let requestPosts = $.ajax({

    url: serviceUrl + "/posts/" + selectedPostId,

    headers: authHeaders });

  let requestComments = $.ajax({ url: serviceUrl + `/comments/?query={"post_id":"${selectedPostId}"}`,

    headers: authHeaders });

  Promise.all([requestPosts, requestComments])

    .then(displayPostWithComments)

    .catch(displayError);

}


33

Solution: Blog – Display Post with Its Comments

function displayPostWithComments([post, comments]) {

  $("#post-title").text(post.title);

  $("#post-body").text(post.body);

  $("#post-comments").empty();

  for (let comment of comments) {

    let commentItem = $("<li>")

      .text(comment.text);

    $("#post-comments")

      .append(commentItem);

  }

}

Check your solution here: https://judge.softuni.bg/Contests/360


Async / Await

Simplified Promises


35

Async / Await Simplify Promises

async function loadData() {

  return new Promise(function(resolve, reject) {

    setTimeout(function() { resolve('data'); }, 300);

  });

}

async function loadMoreData(input) {

  return new Promise(function(resolve, reject) {

    setTimeout(function() { 

      resolve(input + ' + more data'); }, 200);

    });

}


36

Async / Await Simplify Promises (2)

async function loadAllData() {

  console.log('Before promise');

  let data = await loadData();

  let moreData = await loadMoreData(data);

  console.log('Result: ' + moreData);

  console.log('After promise');

}



loadAllData();

console.log('Finished');

Before promise

Finished

Result: data + more data

After promise


37

Transpiling Async / Await with Babel

npm install -g babel-cli

npm install -g babel-plugin-transform-async-to-generator

babel async-await.js -o async-await-transpiled.js

.babelrc

{

  "plugins": ["transform-async-to-generator"]

}


Web Workers

Running Background Tasks in the Browser


39

Web Workers

<p>Count numbers: <output id="result"></output></p>

<button onclick="startWorker()">Start Worker</button>

<button onclick="stopWorker()">Stop Worker</button>

<button onclick="resetWorker()">Reset Worker</button>

<script>

  let worker = undefined;

  function startWorker() {

    worker = new Worker("counter-web-worker.js");

    worker.onmessage = function(event) {

      $("#result").text(event.data);

    };

  }

Receive data from the worker

Run background Web worker


40

Web Workers (2)

  function stopWorker() {

    if (worker) {

      worker.terminate();

      worker = undefined;

    }

  }



  function resetWorker() {

    if (worker)

      worker.postMessage('reset');

  }

</script>


41

Web Workers (2)

let count = 0;

setInterval(function() {

  postMessage(++count);

}, 500);



onmessage = function(e) {

  if (e.data == 'reset')

      count = 0;

};

counter-web-worker.js

Send data to the main script

Receive data from the main script


Practice: Promises,
AJAX, Web Workers

Live Exercises in Class (Lab)

Promises

.then()

.catch()


43

Promises hold operations (background tasks)

Can be resolved or rejected







jQuery AJAX works with promises

Summary

p.then(function(result) { 

  /* process the result */ })

.catch(function(error) { 

  /* handle the error */ });

$.ajax(request)

.then(function(data) { … })

.catch(function(error) { … });


https://softuni.bg/courses/javascript-applications

Asynchronous Programming and Promises


License

This course (slides, examples, demos, videos, homework, etc.)
is licensed under the "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International" license

45


Free Trainings @ Software University

Software University Foundation – softuni.org

Software University – High-Quality Education, Profession and Job for Software Developers

softuni.bg 

	Software University @ Facebook

	facebook.com/SoftwareUniversity

	Software University @ YouTube

	youtube.com/SoftwareUniversity

	Software University Forums – forum.softuni.bg