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

问题描述 投票:0回答:1

我正在努力理解Javascript的承诺,到目前为止这就是我得到的。基本上我试图用setInterval和setTimeout来模拟ajax请求,以了解我如何使用:

promise.progress promise.done promise.fail promise.always promise.catch

下面的console.log()示例显示除fail和catch之外的所有内容。我不知道如何打破代码来触发失败?或者是失败的IS捕获?或者在失败后赶来?

你能帮助我以捕获和处理失败所需的所有方式破解这段代码吗?

$(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>
javascript jquery ajax promise
1个回答
3
投票

我建议阅读一些关于承诺的文章。那些将能够比我更好地解释方式。还尝试在现代浏览器上使用“真正的”承诺。否则,一旦你离开JQuerys deferred(),你将不得不重新学习一些东西,因为它是一个非标准的promises实现,所以API会有所不同。但是,让我们看看我们可以用你的代码做些什么。

1)如果我们想要测试一个承诺的所有可能结果,我们需要在一个可能成功或失败的承诺中做一些事情。 ajax调用就是一个很好的例子。所以让我们创建一个可以工作的函数并稍微更改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)使用myProcess函数并将一些处理程序链接到它。 .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.
    } );

更新:本机承诺包裹在JQuery.get()

最后它非常简单。只要你有异步发生的事情,只需将它包装在一个承诺中,然后继续使用.then()链接。因此,如果我们想宣传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 ) );
        } );
    } );
};

然后,我们可以使用该功能来抓住我们的东西。页面,数据,我们可以获得的任何东西。

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()函数不要求您始终提供拒绝处理程序。如果您只想提供一个错误处理程序,可以在最后使用.catch()。唯一真正缺少的是.progress()方法。 .first()是触发承诺之前的任何代码。

行动承诺的一个完整例子是:

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();
© www.soinside.com 2019 - 2024. All rights reserved.