JavaScript Promise API

The JavaScript Promise API is awesome but can be made amazing with async and await!

JavaScript Promise API很棒,但是可以通过asyncawait变得惊人!

While synchronous code is easier to follow and debug, async is generally better for performance and flexibility. Why "hold up the show" when you can trigger numerous requests at once and then handle them when each is ready?  Promises are becoming a big part of the JavaScript world, with many new APIs being implemented with the promise philosophy. Let's take a look at promises, the API, how it's used!

尽管同步代码更易于跟踪和调试,但异步通常在性能和灵活性方面更好。 当您一次触发多个请求,然后在每个请求准备就绪时处理它们时,为什么要“暂停显示”呢? 承诺正在成为JavaScript世界的重要组成部分,许多新API都以promise理念实现。 让我们来看看Promise,API及其用法!

在野外的应许 (Promises in the Wild)

The XMLHttpRequest API is async but does not use the Promises API.  There are a few native APIs that now use promises, however:

当XMLHttpRequest API是异步,但使用承诺API。 但是,现在有一些本机API使用Promise:

Promises will only become more prevalent so it's important that all front-end developers get used to them.  It's also worth noting that Node.js is another platform for Promises (obviously, as Promise is a core language feature).

承诺只会变得更加普遍,因此所有前端开发人员都必须习惯它们,这一点很重要。 还值得注意的是,Node.js是Promises的另一个平台(显然,Promise是核心语言功能)。

Testing promises is probably easier than you think because setTimeout can be used as your async "task"!

测试Promise可能比您想象的要容易,因为setTimeout可以用作异步“任务”!

基本承诺用法 (Basic Promise Usage)

The new Promise() constructor should only be used for legacy async tasks, like usage of setTimeout or XMLHttpRequest. A new Promise is created with the new keyword and the promise provides resolve and reject functions to the provided callback:

new Promise()构造函数应仅用于旧式异步任务,例如setTimeoutXMLHttpRequest用法。 使用new关键字创建一个新的Promise,promise为所提供的回调提供resolvereject功能:


var p = new Promise(function(resolve, reject) {
	
	// Do an async task async task and then...

	if(/* good condition */) {
		resolve('Success!');
	}
	else {
		reject('Failure!');
	}
});

p.then(function(result) { 
	/* do something with the result */
}).catch(function() {
	/* error :( */
}).finally(function() {
   /* executes regardless or success for failure */ 
});


It's up to the developer to manually call resolve or reject within the body of the callback based on the result of their given task. A realistic example would be converting XMLHttpRequest to a promise-based task:

开发人员可以根据他们给定任务的结果,在回调函数体中手动调用“ resolve或“ reject 。 一个现实的例子是将XMLHttpRequest转换为基于promise的任务:


// From Jake Archibald's Promises and Back:
// http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest

function get(url) {
  // Return a new promise.
  return new Promise(function(resolve, reject) {
    // Do the usual XHR stuff
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = function() {
      // This is called even on 404 etc
      // so check the status
      if (req.status == 200) {
        // Resolve the promise with the response text
        resolve(req.response);
      }
      else {
        // Otherwise reject with the status text
        // which will hopefully be a meaningful error
        reject(Error(req.statusText));
      }
    };

    // Handle network errors
    req.onerror = function() {
      reject(Error("Network Error"));
    };

    // Make the request
    req.send();
  });
}

// Use it!
get('story.json').then(function(response) {
  console.log("Success!", response);
}, function(error) {
  console.error("Failed!", error);
});



Sometimes you don't need to complete an async tasks within the promise -- if it's possible that an async action will be taken, however, returning a promise will be best so that you can always count on a promise coming out of a given function. In that case you can simply call Promise.resolve() or Promise.reject() without using the new keyword. For example:

有时候,你并不需要完成的承诺中异步任务-如果它可能是一个异步将采取行动,然而,返回承诺将最好的,让您可以随时在承诺未来数给定函数的出。 在这种情况下,您可以简单地调用Promise.resolve()Promise.reject()而不使用new关键字。 例如:


var userCache = {};

function getUserDetail(username) {
  // In both cases, cached or not, a promise will be returned

  if (userCache[username]) {
  	// Return a promise without the "new" keyword
    return Promise.resolve(userCache[username]);
  }

  // Use the fetch API to get the information
  // fetch returns a promise
  return fetch('users/' + username + '.json')
    .then(function(result) {
      userCache[username] = result;
      return result;
    })
    .catch(function() {
      throw new Error('Could not find user: ' + username);
    });
}


Since a promise is always returned, you can always use the then and catch methods on its return value!

由于总是返回承诺,因此您可以始终使用thencatch方法获取其返回值!

然后 (then)

All promise instances get a then method which allows you to react to the promise.  The first then method callback receives the result given to it by the resolve() call:

所有的Promise实例都有一个then方法,该方法允许您对Promise做出React。 然后,第一个then方法回调将接收resolve()调用赋予它的结果:


new Promise(function(resolve, reject) {
	// A mock async action using setTimeout
	setTimeout(function() { resolve(10); }, 3000);
})
.then(function(result) {
	console.log(result);
});

// From the console:
// 10


The then callback is triggered when the promise is resolved.  You can also chain then method callbacks:

解决承诺后,将触发then回调。 您还可以链接then方法回调:


new Promise(function(resolve, reject) { 
	// A mock async action using setTimeout
	setTimeout(function() { resolve(10); }, 3000);
})
.then(function(num) { console.log('first then: ', num); return num * 2; })
.then(function(num) { console.log('second then: ', num); return num * 2; })
.then(function(num) { console.log('last then: ', num);});

// From the console:
// first then:  10
// second then:  20
// last then:  40


Each then receives the result of the previous then's return value.

每个then接收前的结果, then的返回值。

If a promise has already resolved but then is called again, the callback immediately fires. If the promise is rejected and you call then after rejection, the callback is never called.

如果一个承诺已经解决,但then再次被调用时,回调将立即触发。 如果承诺被拒绝和你打电话then拒绝后,回调不会被调用。

抓住 (catch)

The catch callback is executed when the promise is rejected:

当承诺被拒绝时,执行catch回调:


new Promise(function(resolve, reject) {
	// A mock async action using setTimeout
	setTimeout(function() { reject('Done!'); }, 3000);
})
.then(function(e) { console.log('done', e); })
.catch(function(e) { console.log('catch: ', e); });

// From the console:
// 'catch: Done!'


What you provide to the reject method is up to you. A frequent pattern is sending an Error to the catch:

您提供给reject方法的取决于您自己。 常见的模式是将Error发送给catch


reject(Error('Data could not be found'));


最后 (finally)

The newly introduced finally callback is called regardless of success or failure:

无论成功与否,都会调用新引入的finally回调:


(new Promise((resolve, reject) => { reject("Nope"); }))
    .then(() => { console.log("success") })
    .catch(() => { console.log("fail") })
    .finally(res => { console.log("finally") });

// >> fail
// >> finally


Promise.all (Promise.all)

Think about JavaScript loaders:  there are times when you trigger multiple async interactions but only want to respond when all of them are completed -- that's where Promise.all comes in.  The Promise.all method takes an array of promises and fires one callback once they are all resolved:

想想JavaScript加载程序:有时候您会触发多个异步交互,但只想在所有异步交互完成后才进行响应-这就是Promise.all进入的地方Promise.all方法采用一组promises并触发一次回调他们都解决了:


Promise.all([promise1, promise2]).then(function(results) {
	// Both promises resolved
})
.catch(function(error) {
	// One or more promises was rejected
});


A perfect way of thinking about Promise.all is firing off multiple AJAX (via fetch) requests at one time:

考虑Promise.all一种完美方法是一次触发多个AJAX(通过fetch )请求:


var request1 = fetch('/users.json');
var request2 = fetch('/articles.json');

Promise.all([request1, request2]).then(function(results) {
	// Both promises done!
});


You could combine APIs like fetch and the Battery API since they both return promises:

您可以结合使用fetch和Battery API之类的API,因为它们都返回承诺:


Promise.all([fetch('/users.json'), navigator.getBattery()]).then(function(results) {
	// Both promises done!
});


Dealing with rejection is, of course, hard. If any promise is rejected the catch fires for the first rejection:

当然,处理拒绝是很难的。 如果任何承诺被拒绝,则第一个拒绝的catch触发:


var req1 = new Promise(function(resolve, reject) { 
	// A mock async action using setTimeout
	setTimeout(function() { resolve('First!'); }, 4000);
});
var req2 = new Promise(function(resolve, reject) { 
	// A mock async action using setTimeout
	setTimeout(function() { reject('Second!'); }, 3000);
});
Promise.all([req1, req2]).then(function(results) {
	console.log('Then: ', results);
}).catch(function(err) {
	console.log('Catch: ', err);
});

// From the console:
// Catch: Second!



Promise.all will be super useful as more APIs move toward promises.

随着越来越多的API向Promise.all将超级有用。

Promise.race (Promise.race)

Promise.race is an interesting function -- instead of waiting for all promises to be resolved or rejected, Promise.race triggers as soon as any promise in the array is resolved or rejected:

Promise.race是一个有趣的功能Promise.race无需等待所有诺言被解决或拒绝, Promise.race在阵列中的任何诺言被解决或拒绝时Promise.race触发:


var req1 = new Promise(function(resolve, reject) { 
	// A mock async action using setTimeout
	setTimeout(function() { resolve('First!'); }, 8000);
});
var req2 = new Promise(function(resolve, reject) { 
	// A mock async action using setTimeout
	setTimeout(function() { resolve('Second!'); }, 3000);
});
Promise.race([req1, req2]).then(function(one) {
	console.log('Then: ', one);
}).catch(function(one, two) {
	console.log('Catch: ', one);
});

// From the console:
// Then: Second!


A use case could be triggering a request to a primary source and a secondary source (in case the primary or secondary are unavailable).

用例可能会触发对主要来源和次要来源的请求(如果主要来源或次要来源不可用)。

习惯承诺 (Get Used to Promises)

Promises have been a hot topic for the past few years (or the last 10 years if you were a Dojo Toolkit user) and they've gone from a JavaScript framework pattern to a language staple.  It's probably wise to assume you'll be seeing most new JavaScript APIs being implemented with a promise-based pattern...

在过去的几年中(或者,如果您是Dojo Toolkit用户,则是过去的十年),承诺一直是一个热门话题,并且它们已经从JavaScript框架模式变成了语言的主要内容。 假设您将看到大多数新JavaScript API正在使用基于承诺的模式来实现,这可能是明智的……

...and that's a great thing!  Developers are able to avoid callback hell and async interactions can be passed around like any other variable.  Promises take some time getting used to be the tools are (natively) there and now is the time to learn them!

...那真是太好了! 开发人员可以避免回调地狱,并且可以像其他任何变量一样传递异步交互。 承诺要花一些时间才能习惯这些工具(本地),现在是时候学习它们了!

翻译自: https://davidwalsh.name/promises

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值