简体   繁体   English

完整的Javascript Promise错误处理。 怎么样?

[英]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: 基本上,我尝试使用setIntervalsetTimeout模拟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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM