JavaScript的promises


Graceful asynchronous programming with Promises 优雅的异步编程with promises

Essentially, a Promise is an object that represents an intermediate state of an operation. 是一个对象代表操作的中间状态。

举个例子:用户视频聊天应用,用户有个好友列表的窗口,点击好友旁边的视频按钮,发起视频的时候,先要calls getUserMedia()获得用户摄像头和麦克风的权限,要先询问用户,等用户同意后,才能返回MediaStream.
getUserMedia()返回一个promise,一旦可用,resolved with the MediaStream.

The code that the video chat application would use might look something like this:

function handleCallButton(evt) {
  setStatusMessage("Calling...");
  navigator.mediaDevices.getUserMedia({video: true, audio: true})
    .then(chatStream => {
      selfViewElem.srcObject = chatStream;
      chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream));
      setStatusMessage("Connected");
    }).catch(err => {
      setStatusMessage("Failed to connect");
    });
}



The important thing here is that the getUserMedia() call returns almost immediately, even if the camera stream hasn't been obtained yet. Even if the handleCallButton() function has already returned to the code that called it, when getUserMedia() has finished working, it calls the handler you provide. As long as the app doesn't assume that streaming has begun, it can just keep on running.

重要的是  getUserMedia()调用立刻返回,虽然摄像头流媒体还没有获得。even if 即使当handleCallButton(env)函数也返回了, 当getUserMedia()完成后调用你提供的callback(promise)函数.  只要程序不认为 streaming已经开始,他就会继续运行。


callback有啥问题
了解了callback的问题,就知道了promise的好处。

chooseToppings(function(toppings) {
  placeOrder(toppings, function(order) {
    collectOrder(order, function(pizza) {
      eatPizza(pizza);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);



chooseToppings()
.then(function(toppings) {
  return placeOrder(toppings);
})
.then(function(order) {
  return collectOrder(order);
})
.then(function(pizza) {
  eatPizza(pizza);
})
.catch(failureCallback);

Or even this:

chooseToppings()
.then(toppings => placeOrder(toppings))
.then(order => collectOrder(order))
.then(pizza => eatPizza(pizza))
.catch(failureCallback);

This works because with arrow functions () => x is valid shorthand for () => { return x; }.

You could even do this, since the functions just pass their arguments directly, so there isn't any need for that extra layer of functions:

chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);


This is not quite as easy to read, however, and this syntax might not be usable if your blocks are more complex than what we've shown here.

At their most basic, promises are similar to event listeners, but with a few differences:

  • A promise can only succeed or fail once. It cannot succeed or fail twice and it cannot switch from success to failure or vice versa once the operation has completed.
  • If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier.
阅读量: 534
发布于:
修改于: