
console.log('1') console.log('2') console.log('3') console.log('1') setTimeout(function afterTwoSeconds() { console.log('2') }, 2000) console.log('3') setTimeout function was called. The callback will be called, in this example, after 2 seconds. The application will not stop while waiting for the two seconds to expire. Instead, its execution will continue, and when the timer fires, the afterTwoSeconds function will be called.
XMLHttpRequest (XHR), but you can easily use jQuery ( $.ajax ) here, or the more modern standard approach, based on the use of the function fetch . Both that and another is reduced to use of promises. The code, depending on the campaign, will change, but here, for a start, this example: // url - 'https://api.github.com/users/daspinola/repos' function request(url) { const xhr = new XMLHttpRequest(); xhr.timeout = 2000; xhr.onreadystatechange = function(e) { if (xhr.readyState === 4) { if (xhr.status === 200) { // } else { // } } } xhr.ontimeout = function () { // , , } xhr.open('get', url, true) xhr.send(); } // "doThis" , - "andThenThis". "doThis" , , , , "andThenThis". doThis(andThenThis) // "doThis" "callback" , , , function andThenThis() { console.log('and then this') } // , , , "callback" - function doThis(callback) { console.log('this first') // , , , , , '()', callback() } request function: function request(url, callback) { const xhr = new XMLHttpRequest(); xhr.timeout = 2000; xhr.onreadystatechange = function(e) { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.response) } else { callback(xhr.status, null) } } } xhr.ontimeout = function () { console.log('Timeout') } xhr.open('get', url, true) xhr.send(); } callback parameter, therefore, after executing the request and receiving the server response, the callback will be called both in case of an error and in case of successful completion of the operation. const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users` request(userGet, function handleUsersList(error, users) { if (error) throw error const list = JSON.parse(users).items list.forEach(function(user) { request(user.repos_url, function handleReposList(err, repos) { if (err) throw err // }) }) }) handleUsersList handleUsersList is handleUsersList ;SON.parse , convert it, for convenience, into an object;repos_url is the URL for our next requests, and we got it from the first request.handleReposList . Here, as well as when loading a list of users, you can handle errors or useful data, which contain a list of user repositories. try { request(userGet, handleUsersList) } catch (e) { console.error('Request boom! ', e) } function handleUsersList(error, users) { if (error) throw error const list = JSON.parse(users).items list.forEach(function(user) { request(user.repos_url, handleReposList) }) } function handleReposList(err, repos) { if (err) throw err // console.log('My very few repos', repos) } forEach loop, here are three, is that such code is hard to read and maintain. A similar problem exists, perhaps, from the day the callback functions appeared, it is widely known as callback hell.
const myPromise = new Promise(function(resolve, reject) { // if (codeIsFine) { resolve('fine') } else { reject('error') } }) myPromise .then(function whenOk(response) { console.log(response) return response }) .catch(function notOk(err) { console.error(err) }) resolve and reject methods;Promise constructor. If the code is executed successfully, call the resolve method, if not, reject ;resolve , the .then method for the Promise object will be executed; similarly, if reject is called, the .catch method will be executed.resolve and reject methods take only one parameter; as a result, for example, when executing a command of the type resolve('yey', 'works') , only 'yey' will be passed to the callback .then ;.then calls at the end of the corresponding callbacks, you should always use return , otherwise they will all be executed at the same time, and this is obviously not what you want to achieve;reject command is executed, if the next in the chain goes .then , it will be executed (you can consider .then expression that is executed in any case);.then calls in one of them, the next ones will be skipped until the expression .catch is found;resolve or reject , as well as the states “resolved” and “rejected”, which correspond to a successful, with a call to resolve , and unsuccessful, with a call to reject , completion of the work of promis. When the promise is in the “resolved” or “rejected” state, it cannot be changed. function request(url) { return new Promise(function (resolve, reject) { const xhr = new XMLHttpRequest(); xhr.timeout = 2000; xhr.onreadystatechange = function(e) { if (xhr.readyState === 4) { if (xhr.status === 200) { resolve(xhr.response) } else { reject(xhr.status) } } } xhr.ontimeout = function () { reject('timeout') } xhr.open('get', url, true) xhr.send(); }) } request , the following will be returned.
request function, we will rewrite the rest of the code. const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users` const myPromise = request(userGet) console.log('will be pending when logged', myPromise) myPromise .then(function handleUsersList(users) { console.log('when resolve is found it comes here with the response, in this case users ', users) const list = JSON.parse(users).items return Promise.all(list.map(function(user) { return request(user.repos_url) })) }) .then(function handleReposList(repos) { console.log('All users repos in an array', repos) }) .catch(function handleErrors(error) { console.log('when a reject is executed it will come here ignoring the then statement ', error) }) .then with the successful resolution of promise. We have a list of users. In the second expression .then we pass an array with repositories. If something went wrong, we’ll end up in a .catch expression. const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users` const userRequest = request(userGet) // , userRequest .then(handleUsersList) .then(repoRequest) .then(handleReposList) .catch(handleErrors) function handleUsersList(users) { return JSON.parse(users).items } function repoRequest(users) { return Promise.all(users.map(function(user) { return request(user.repos_url) })) } function handleReposList(repos) { console.log('All users repos in an array', repos) } function handleErrors(error) { console.error('Something went wrong ', error) } .then expressions reveals the meaning of the call to userRequest . The code is easy to work with and easy to read.function . Using generators, asynchronous code can be made very similar to synchronous. For example, it may look like this: function* foo() { yield 1 const args = yield 2 console.log(args) } var fooIterator = foo() console.log(fooIterator.next().value) // 1 console.log(fooIterator.next().value) // 2 fooIterator.next('aParam') // console.log 'aParam' return , use the expression yield , which stops the execution of the function until the next call to the .next iterator. This is similar to the expression .then in promises, which is performed when promise is resolved.request function: function request(url) { return function(callback) { const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(e) { if (xhr.readyState === 4) { if (xhr.status === 200) { callback(null, xhr.response) } else { callback(xhr.status, null) } } } xhr.ontimeout = function () { console.log('timeout') } xhr.open('get', url, true) xhr.send() } } url argument, but instead of immediately executing the request, we want to execute it only when we have a callback function to process the response. function* list() { const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users` const users = yield request(userGet) yield for (let i = 0; i<=users.length; i++) { yield request(users[i].repos_url) } } request function, which it receives the url and returns the function that expects the callback);users , to be ready to be sent to the next .next ;users array and expect, for each of them, .next , returning, for each, the corresponding callback. try { const iterator = list() iterator.next().value(function handleUsersList(err, users) { if (err) throw err const list = JSON.parse(users).items // iterator.next(list) list.forEach(function(user) { iterator.next().value(function userRepos(error, repos) { if (error) throw repos // console.log(user, JSON.parse(repos)) }) }) }) } catch (e) { console.error(e) } async , which function is supposed to be performed asynchronously, and using await , tell the system what part of the code should wait for the permission of the corresponding promise. sumTwentyAfterTwoSeconds(10) .then(result => console.log('after 2 seconds', result)) async function sumTwentyAfterTwoSeconds(value) { const remainder = afterTwoSeconds(20) return value + await remainder } function afterTwoSeconds(value) { return new Promise(resolve => { setTimeout(() => { resolve(value) }, 2000); }); } sumTwentyAfterTwoSeconds ;afterTwoSeconds , which can end with a call to resolve or reject ;.then , where the operation marked with the await keyword is completed, in this case it is just one operation.request function for use in the async/await construction: function request(url) { return new Promise(function(resolve, reject) { const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(e) { if (xhr.readyState === 4) { if (xhr.status === 200) { resolve(xhr.response) } else { reject(xhr.status) } } } xhr.ontimeout = function () { reject('timeout') } xhr.open('get', url, true) xhr.send() }) } async , in which we use the await keyword: async function list() { const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users` const users = await request(userGet) const usersList = JSON.parse(users).items usersList.forEach(async function (user) { const repos = await request(user.repos_url) handleRepoList(user, repos) }) } function handleRepoList(user, repos) { const userRepos = JSON.parse(repos) // console.log(user, userRepos) } list function that will process the request. We also need the async/await construction in a forEach loop to form a list of repositories. Calling all this is very simple: list() .catch(e => console.error(e)) async/await can be found here .async/await , like the minus of the generators, is that the old browsers do not support this design, and for its use in server development you need to use Node 8. In this situation, again, a transpiler will help, for example, babel .async/await . If you want to properly deal with what we talked about - experiment with this code and with all the technologies discussed.$.ajax and fetch . If you have ideas on how to improve the quality of the code using the methods described above, I will be grateful if you tell me about it.Source: https://habr.com/ru/post/337662/
All Articles