async / await
. // ajax(..) - Ajax- var response = ajax('https://example.com/api'); console.log(response); // response api
ajax(..)
function, immediately after its call, cannot return some value that could be assigned to the response
variable. ajax('https://example.com/api', function(response) { console.log(response); // response api });
// , jQuery jQuery.ajax({ url: 'https://api.example.com/endpoint', success: function(response) { // - . }, async: false // - , });
setTimeout(callback, milliseconds)
function. It allows you to schedule the execution of events (setting a time-out) that should occur after the moment when the function is called. Consider an example: function first() { console.log('first'); } function second() { console.log('second'); } function third() { console.log('third'); } first(); setTimeout(second, 1000); // second 1000 third();
first third second
setTimeout
described above), it did not contain any built-in asynchronous programming mechanisms. JS engines were only doing single-threaded execution of certain code fragments, one at a time.response
variable inside the callback, and the JS engine tells the environment: “Listen, I'm going to pause the program, but when you finish this network request and get some data, please call this callback. ” console.log('Hi'); setTimeout(function cb1() { console.log('cb1'); }, 5000); console.log('Bye');
console.log('Hi')
command is added to the call stack.console.log('Hi')
command is executed.console.log('Hi')
command is removed from the call stack.setTimeout(function cb1() { ... })
command is added to the call stack.setTimeout(function cb1() { ... })
command is executed. The browser creates a timer that is part of the Web API. It will perform a countdown.setTimeout(function cb1() { ... })
command has completed and is removed from the call stack.console.log('Bye')
command is added to the call stack.console.log('Bye')
command is executed.console.log('Bye')
is removed from the call stack.cb1
, the timer ends and puts the cb1 cb1
on the callback queue.cb1
function from the cb1
queue and pushes it onto the call stack.cb1
function cb1
executed and adds console.log('cb1')
to the call stack.console.log('cb1')
is executed.console.log('cb1')
command console.log('cb1')
is removed from the call stack.cb1
is removed from the call stack.setTimeout(…)
does not automatically place a callback in the event loop queue. This command starts the timer. When the timer is triggered, the environment puts the callback in the event loop, as a result, during some of the future ticks, this callback will be taken into work and executed. Take a look at this code snippet: setTimeout(myCallback, 1000);
myCallback
will be executed in 1000 ms. It would be more correct to say that in 1000 ms. myCallback
will be added to the queue. In the queue, however, there may be other events added there earlier, as a result, our callback will have to wait.setTimeout(callback, 0)
command in them. Now you know how the event loop works and what happens when you call setTimeout
. Given this, it is quite obvious that a call to setTimeout
with the second argument equal to 0 simply postpones the callback call until the call stack is cleared. console.log('Hi'); setTimeout(function() { console.log('callback'); }, 0); console.log('Bye');
Hi Bye callback
while(true)
.etTimeout(callback, 0)
, but implemented in such a way that they allow the observance of a sequence of operations that are performed later, but as soon as possible. listen('click', function (e){ setTimeout(function(){ ajax('https://api.example.com/endpoint', function (text){ if (text == "hello") { doSomething(); } else if (text == "world") { doSomethingElse(); } }); }, 500); });
click
event, then wait for the timer to trigger, and finally, wait for the arrival of an Ajax response, after which it can all happen again. listen('click', function (e) { // .. });
setTimeout(function(){ // .. }, 500);
ajax('https://api.example.com/endpoint', function (text){ // .. });
if (text == "hello") { doSomething(); } else if (text == "world") { doSomethingElse(); }
var x = 1; var y = 2; console.log(x + y);
x
and y
added and displayed in the console. But what if the value of x
or y
not available and it has yet to be set? Let's say we need to get from the server what will be written in x
and y
, and then use this data in the expression. Imagine that we have the functions loadX
and loadY
, which, respectively, load x
and y
values ​​from the server. Then imagine that there is a sum
function that adds the x
and y
values ​​as they are loaded. function sum(getX, getY, callback) { var x, y; getX(function(result) { x = result; if (y !== undefined) { callback(x + y); } }); getY(function(result) { y = result; if (x !== undefined) { callback(x + y); } }); } // , `x` function fetchX() { // .. } // , `y` function fetchY() { // .. } sum(fetchX, fetchY, function(result) { console.log(result); });
x
and y
as values ​​that will be received in the future, and we describe the operation sum(…)
(when called without going into the implementation details) as if it doesn't matter to execute , whether or not the x
and y
values ​​are available at the time of its call.x + y
operation using promises: function sum(xPromise, yPromise) { // `Promise.all([ .. ])` , // , // , return Promise.all([xPromise, yPromise]) // , // `X` `Y` . .then(function(values){ // `values` - // return values[0] + values[1]; } ); } // `fetchX()` `fetchY()` // . // ** **. sum(fetchX(), fetchY()) // // . // `then(...)` // . .then(function(sum){ console.log(sum); });
fetchX()
and fetchY()
are executed directly, and the values ​​they return (promises!) Are passed to sum(...)
. Those values ​​that represent these promises may be ready for further use now or later, but each promise behaves in such a way that the moment of accessibility of values ​​is not important in itself. As a result, we reason about the values ​​of x
and y
without reference to time. These are future values.Promise.all([ ... ])
) the sum(…)
call sum(…)
. We expect the value that this promise will return, causing then(…)
. When the operation sum(…)
completed, our future value of the amount is ready and we can display it on the screen. We hide the logic of waiting for future x
and y
values ​​inside sum(…)
.sum(…)
Promise.all([ … ])
( promiseX
promiseY
). .then(…)
, values[0] + values[1]
( , ). , then(…)
, , , sum(…)
, , , Promise.all([ ... ])
. , then(…)
, , , , . , .then(…)
.then(…)
, , . — , . — , : sum(fetchX(), fetchY()) .then( // function(sum) { console.log( sum ); }, // function(err) { console.error( err ); // - } );
x
y
- , , , s um(…)
, . , then(…)
, . . function delay(time) { return new Promise(function(resolve, reject){ setTimeout(resolve, time); }); } delay(1000) .then(function(){ console.log("after 1000ms"); return delay(2000); }) .then(function(){ console.log("after another 2000ms"); }) .then(function(){ console.log("step 4 (next Job)"); return delay(5000); }) // ...
delay(2000)
, 2000 ., then(…)
, , then(…)
2000 .Promise
. , , , .new Promise(…)
, , , p instanceof Promise
. However, this is not quite true.Promise
, , . , , .TypeError
ReferenceError
, . var p = new Promise(function(resolve, reject){ foo.bar(); // `foo` , ! resolve(374); // :( }); p.then( function fulfilled(){ // :( }, function rejected(err){ // `err` `TypeError` // `foo.bar()`. } );
then(…)
)? , , , , : var p = new Promise( function(resolve,reject){ resolve(374); }); p.then(function fulfilled(message){ foo.bar(); console.log(message); // }, function rejected(err){ // } );
foo.bar()
«». , . , , . , p.then(…)
, TypeError
.done(…)
, , «». done(…)
, , done(…)
, , , , .done(…)
( ): var p = Promise.resolve(374); p.then(function fulfilled(msg){ // , // console.log(msg.toLowerCase()); }) .done(null, function() { // , });
async / await
, . , async / await
, .async
. AsyncFunction . , , .Promise
. , Promise
, , . , async
, , .async
, await
, , . async- , , , .async / await
, . // - JS- function getNumber1() { return Promise.resolve('374'); } // , getNumber1 async function getNumber2() { return 374; }
function f1() { return Promise.reject('Some error'); } async function f2() { throw 'Some error'; }
await
, async
. . async-, then
: async function loadData() { // `rp`- request-promise. var promise1 = rp('https://api.example.com/endpoint1'); var promise2 = rp('https://api.example.com/endpoint2'); // // . var response1 = await promise1; var response2 = await promise2; return response1 + ' ' + response2; } // , `async` // `then` Promise loadData().then(() => console.log('Done'));
function
. , , , , . IIFE (Immediately Invoked Function Expression, ), . var loadData = async function() { // `rp`- request-promise. var promise1 = rp('https://api.example.com/endpoint1'); var promise2 = rp('https://api.example.com/endpoint2'); // // . var response1 = await promise1; var response2 = await promise2; return response1 + ' ' + response2; }
async / await
.async / await
, , .async / await
. , async / await
, . — .then()
, , - , , . / `rp`- request-promise. rp('https://api.example.com/endpoint1').then(function(data) { // … });
async / await
: // `rp`- request-promise. var response = await rp('https://api.example.com/endpoint1');
async / await
. , try / catch
..catch()
, try / catch
: function loadData() { try { // . getJSON().then(function(response) { var parsed = JSON.parse(response); console.log(parsed); }).catch(function(e) { // console.log(e); }); } catch(e) { console.log(e); } }
async / await
: async function loadData() { try { var data = JSON.parse(await getJSON()); console.log(data); } catch(e) { console.log(e); } }
async / await
, . — , : function loadData() { return getJSON() .then(function(response) { if (response.needsAnotherRequest) { return makeAnotherRequest(response) .then(function(anotherResponse) { console.log(anotherResponse) return anotherResponse }) } else { console.log(response) return response } }) }
async / await
: async function loadData() { var response = await getJSON(); if (response.needsAnotherRequest) { var anotherResponse = await makeAnotherRequest(response); console.log(anotherResponse) return anotherResponse } else { console.log(response); return response; } }
async / await
, , , , . : function loadData() { return callAPromise() .then(callback1) .then(callback2) .then(callback3) .then(() => { throw new Error("boom"); }) } loadData() .catch(function(e) { console.log(err); // Error: boom at callAPromise.then.then.then.then (index.js:8:13) });
async / await
: async function loadData() { await callAPromise1() await callAPromise2() await callAPromise3() await callAPromise4() await callAPromise5() throw new Error("boom"); } loadData() .catch(function(e) { console.log(err); // // Error: boom at loadData (index.js:7:9) });
.then
«step-over», .then
, «» . async / await
, await
, — .async / await
. , , , . ( ) a sync / await
.Source: https://habr.com/ru/post/340508/
All Articles