【JavaScript】Promise

Promise

promise 所执行的任务

事件对于同一对象上发生多次的事情(如 keyup、touchstart 等)非常有用。对于这些事件,实际您并不关注在添加侦听器之前所发生的事情。但是,如果关系到异步成功/失败,理想的情况是您希望:

img1.callThisIfLoadedOrWhenLoaded(function() {
  // loaded
}).orIfFailedCallThis(function() {
  // failed
});

// and…
whenAllTheseHaveLoaded([img1, img2]).callThis(function() {
  // all loaded
}).orIfSomeFailedCallThis(function() {
  // one or more failed
});

这就是 promise 所执行的任务。

如果 HTML 图像元素有一个返回 promise 的“ready”方法,我们可以执行:

img1.ready().then(function() {
  // loaded
}, function() {
  // failed
});

// and…
Promise.all([img1.ready(), img2.ready()]).then(function() {
  // all loaded
}, function() {
  // one or more failed
});

Promise两个特点

Promise 有点类似于事件侦听器,但有以下两点区别:

1. promise 只能成功或失败一次,而不能成功或失败两次,也不能从成功转为失败或从失败转为成功。
2. 如果 promise 已成功或失败,且您之后添加了成功/失败回调,则将会调用正确的回调,即使事件发生在先。

Promise状态

1. A promise is fulfilled if promise.then(f) will call f "as soon as possible."
2. A promise is rejected if promise.then(undefined, r) will call r "as soon as possible."
3. A promise is pending if it is neither fulfilled nor rejected.

创建 promise 的步骤

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

Promise 构造函数包含一个参数和一个带有 resolve(解析)和 reject(拒绝)两个参数的回调。在回调中执行一些操作(例如异步),如果一切都正常,则调用 resolve,否则调用 reject.

Promise 的使用示例

promise.then(function(result) {
  console.log(result); // "Stuff worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});

then() 包含两个参数:一个用于成功情形的回调和一个用于失败情形的回调。这两个都是可选的,因此您可以只添加一个用于成功情形或失败情形的回调。

实例

  1. 启动一个转环来提示加载
  2. 获取一个故事的 JSON,确定每个章节的标题和网址
  3. 向页面中添加标题
  4. 获取每个章节
  5. 向页面中添加故事
  6. 停止转环
  7. 但如果此过程发生错误,也要向用户显示。我们也想在那一点停止转环,否则,它将不停地旋转、眩晕并撞上其他 UI 控件。

从网络中获取数据:

对 XMLHttpRequest 执行 promise

编写一个作出 GET 请求的简单函数

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();
  });
}

使用该功能

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

现在我们无需手动键入 XMLHttpRequest 即可作出 HTTP 请求。

返回新值会改变值

var promise = new Promise(function(resolve, reject) {
  resolve(1);
});

promise.then(function(val) {
  console.log(val); // 1
  return val + 2;
}).then(function(val) {
  console.log(val); // 3
})

异步操作队列

可以链接多个 then,以便按顺序运行异步操作。

当从 then() 回调中返回某些内容时,这有点儿神奇。如果返回一个值,则会以该值调用下一个 then()。但是,如果您返回类似于 promise 的内容,下一个 then() 则会等待,并仅在 promise 产生结果(成功/失败)时调用。例如:

getJSON('story.json').then(function(story) {
  return getJSON(story.chapterUrls[0]);
}).then(function(chapter1) {
  console.log("Got chapter 1!", chapter1);
})

http://caibaojian.com/promise...
https://github.com/googlesamp...

相关推荐