[英]Complete Javascript Promise error handling. How?
I am trying to understand Javascript promises and so far this is what I got. 我正在尝试了解Javascript承诺,到目前为止,这就是我所得到的。 Basically I am trying to simulate ajax requests with setInterval and setTimeout to understand how I can use:
基本上,我尝试使用setInterval和setTimeout模拟ajax请求,以了解如何使用:
promise. 诺言。 progress
进展
promise. 诺言。 done
完成
promise. 诺言。 fail
失败
promise. 诺言。 always
总是
promise. 诺言。 catch
抓住
The console.log() example below shows everything except fail and catch. 下面的console.log()示例显示了除故障和捕获之外的所有内容。 I have no idea how to break the code to trigger catch on a fail?
我不知道如何破坏代码以触发失败捕获? Or fail IS catch?
还是IS捕获失败? Or catch comes after fail??!
还是追赶失败之后??!
Can you help me break this code in all of the ways required to catch and handle a fail? 您能帮助我以捕获和处理失败所需的所有方式破坏此代码吗?
$(document).ready(function() { console.log('1. Document is ready.'); var timer; var i = 1; // Declare and Call the promise. var promise = myProcess(); promise.progress(function() { // Receives updates from deferred.notify(); // deferred.notify updates promise.progress on every Tick of timer = setInterval console.clear(); console.log('promise.progress.. ' + i++); }); promise.done(function() { // deferred.resolve triggers at the end of setTimeout console.log('promise.done'); }); promise.fail(function(error) { // Executes on fail... console.log('promise.fail'); }); promise.always(function() { // Executes always... console.log('promise.always'); //console.log(myProcess()); }); function myProcess() { var deferred = $.Deferred(); timer = setInterval(function() { // Tick every 1 second... deferred.notify(); }, 1000); // until the 3rd second... setTimeout(function() { clearInterval(timer); deferred.resolve(); }, 3000); return deferred.promise(); } });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
I'd suggest reading some articles about promises. 我建议阅读一些有关诺言的文章。 Those will be able to explain way better than I can.
这些将比我能更好地解释。 Also try working with the 'real' promises on a modern browser.
也可以尝试在现代浏览器上使用“真实”承诺。 Else you'll have to relearn some things once you switch away from JQuerys deferred(), since it's a non-standard implementation of promises, so the API will differ.
否则,一旦您离开JQuerys deferred(),您将不得不重新学习一些事情,因为它是Promise的非标准实现,因此API会有所不同。 But let's see what we can do with your code.
但是,让我们看看我们可以如何处理您的代码。
1) If we want to test all the possible outcomes of a promise, we need to actually do something inside a promise that can either succeed or fail. 1)如果我们要测试承诺的所有可能结果,则需要在承诺内进行一些可能成功或失败的事情。 An ajax call is a good example for it.
一个ajax调用就是一个很好的例子。 So let's create a function that does work and change the myProcess function a bit so it makes an ajax call to an uri we provide.
因此,让我们创建一个可以正常工作的函数,并稍微更改myProcess函数,以便对我们提供的uri进行ajax调用。
var myProcess = function myProcess( uri ) {
var deferred = $.Deferred();
// Keep the timer so the .progress() method will get triggered.
// In the example of an ajax call, you'd probably want to bind this to either the readystatechange event or to some work the callback of $.get() executes.
timer = setInterval(function() {
// Tick every 1 second...
deferred.notify();
}, 1000);
// Make an ajax call. If it suceeeds, resolve, else reject
// Since an ajax call is already async, we don't need to simulate the waiting with the timeout.
$.get( uri, function( data ) {
// remove the timer again once the ajax result returns.
clearInterval( timer );
if ( data ) deferred.resolve( data );
else deferred.reject( data );
} );
return deferred.promise();
};
2) Use the myProcess function and link some handlers to it. 2)使用myProcess函数并将一些处理程序链接到该函数。 The .done() method is equivalent to the .then() method of standard Promises.
.done()方法等效于标准Promises的.then()方法。
myProcess( 'http://some.api.uri/' )
// This will get triggered every second as long as the timer is active.
// If you want this to take longer for testing purposes, just make the ajax call take longer by adding a setTimeout again.
.progress( function onProgress() {
// The promise is still being resolved. Every second this gets triggered because we have deferred.notify() inside myProcess().
} )
// This will trigger once the ajax call succeeds succesfully and hence, .resolve() is triggered.
.done( function onResolved_1( data ) {
// Do something with the data you received from the ,get() call inside myProcess.
return JSON.parse( data );
} )
// This will trigger after the previous .done() function ( onResolved_1 ) has returned the data.
.done( function onResolved_2( dataReturnedFromPreviousDone ) {
// Do something with the data we parsed.
} )
// This will only trigger if the ajax call fails and hence, .reject() gets triggered.
.fail( function onFail( error ) {
// Do something with the error.
} )
// This will happen no matter if the promise gets resolved or rejected.
.always( function always() {
// stuff that always needs to happen.
} );
UPDATE: Native promises wrapped around JQuery.get() 更新:本地承诺环绕JQuery.get()
In the end it's pretty simple. 最后,它非常简单。 Any time you have something that happens async, just wrap it in a promise and continue from there with
.then()
chaining. 每当您发生异步事件时,只需将其包装在promise中,然后从那里继续进行
.then()
链接。 So if we want to promisify JQuery .get(), we can use the following basic wrapper: 因此,如果我们要推广JQuery .get(),则可以使用以下基本包装器:
var getURI = function getURI( uri ) {
// Wrap the basic $.get() function into a native promsie object.
// The promise constructor expects a function that will take in the resolve and reject methods as parameters
return new Promise( function( resolve, reject ) {
$.get( uri, function( data ) {
if ( data ) resolve( data );
else reject( new Error( 'could not load uri: ' + uri ) );
} );
} );
};
Then again, we can use that function to grab us something. 再说一次,我们可以使用该函数来抓取我们一些东西。 A page, data, anything that we can GET.
页面,数据以及我们可以获取的任何内容。
var getData = function getData( callback ) {
// Do any work that you want to happen before the GET call
console.log( 'this always happens before we fetch the data' );
// Make the request for the data. Let's assume it returns us a text structured as JSON.
getURI( 'https://postman-echo.com/get?foo1=bar1&foo2=bar2' )
// .then() accepts two functions. One to trigger after resolve() and one to trigger after reject()
.then(
function onResolve( data ) {
// do something with the data
// If the only thing you do with the data is returning the result of a function, you don't have to wrap that function.
// So if we only want to parse, we can just use .then( JSON.parse )
return data;
},
function onReject( error ) {
// do something with the error.
console.log( 'error thrown inside onReject() after getURI failed to get data.' );
console.error( error );
}
} )
// Anything you return from inside the onResolve() function will get used as the parameter for the next onResolve() function in the chain.
.then( function( data ) {
// do something else.
// instead of using a callback, you could also return the promise and keep chaining from there.
callback( data );
} );
};
.then()
functions do not require you to always provide a reject handler. .then()
函数不需要您始终提供拒绝处理程序。 If you only want to provide one error handler, you can use .catch()
at the end. 如果只想提供一个错误处理程序,则可以在末尾使用
.catch()
。 The only thing really missing is the .progress()
method. 唯一真正缺少的是
.progress()
方法。 .first()
is any code before triggering a promise. .first()
是触发诺言之前的任何代码。
A full example of promises in action would be this: 兑现承诺的一个完整例子是:
var getURI = function getURI( uri ) {
return new Promise( function( resolve, reject ) {
$.get( uri, function( data ) {
if ( data ) resolve( data );
else reject( new Error( 'could not load uri: ' + uri ) );
} );
} );
};
var doThisFirst = function doThisFirst() {
console.log( 'this should be the first log to appear' );
};
var doThisLast = function doThisLast() {
console.log( 'this.should always be the last log' );
};
var addMeta = function addMeta( obj ) {
obj.meta = 'extra meta data';
return obj;
};
var renderData = function renderData( obj ) {
console.log( 'we received the following object and added a meta property to it: ' );
console.dir( obj );
};
var handleError = function handleError( error ) {
console.log( 'we found an error while fetching and augmenting some data' );
console.error( error );
};
var runApplication = function runApplication() {
doThisFirst();
getURI( 'https://postman-echo.com/get?foo1=bar1&foo2=bar2' )
.then( JSON.parse )
.then( addMeta )
.then( renderData )
.then( doThisLast )
.catch( handleError );
};
runApplication();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.