Promise快速上手

一、回调地狱

在没有Promise之前,如果我们想要操作多个异步函数,会有回调地狱

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

同时这种写法还有另外两个问题:

  1. 回调函数命名缺乏规范, 每个程序员都有可能给回调函数起不同的名字
  2. 不能很好地捕获错误

二、初探Promise

Promise可以完美解决以上三个问题,即

  • 解决回调地狱,增强代码可读性
  • 规范回调的名字或顺序
  • 很方便地捕获错误

而有了Promise后, 相同的操作可以写成:

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

以上的回调函数还可以简化为箭头函数

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);

三、怎么写一个Promise

promise对象是由window.Promise构造函数得到的一个对象

从0开始新建一个promise对象:

Promise 对象是由关键字 new 及其构造函数来创建的。该构造函数接受两个函数——resolvereject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。

resolve函数和reject函数都只接受一个参数

const myFirstPromise = new Promise((resolve, reject) => {
  // ?做一些异步操作,最终会调用下面两者之一:
  //
  //   resolve(someValue); // fulfilled
  // ?或
  //   reject("failure reason"); // rejected
});

想让一个函数有Promise对象的功能:

return new Promose( (resolve, reject) => { )

function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText); // 成功就调用resolve函数
    xhr.onerror = () => reject(xhr.statusText);  // 失败就调用reject函数
    xhr.send();
  });
};

基础示例

let myFirstPromise = new Promise(function(resolve, reject){
    //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
    //在本例中,我们使用setTimeout(...)来模拟异步代码,实际编码时可能是XHR请求或是HTML5的一些API方法.
    setTimeout(function(){
        resolve("成功!"); //代码正常执行!
    }, 250);
});

myFirstPromise.then(function(successMessage){
    //successMessage的值是上面调用resolve(...)方法传入的值.
    //successMessage参数不一定非要是字符串类型,这里只是举个例子
    console.log("Yay! " + successMessage);
}, function(errorMessage){
   // reject会调用这个函数
});

易混淆点:resolve 和 reject  和 then(succes, fail)

new Promise(function(resolve, reject){}里的resolve 和 reject 并不是 .then(succes, fail) 里面的 success 和 fail,

resolve 会去调用 success,reject 会去调用 fail

 

AJAX+Promise请求图片示例

源码地址:https://github.com/mdn/js-examples/blob/master/promises-test/index.html

function imgLoad(url) {
    // Create new promise with the Promise() constructor;
    // This has as its argument a function
    // with two parameters, resolve and reject
    return new Promise(function(resolve, reject) {
      // Standard XHR to load an image
      let request = new XMLHttpRequest();
      request.open('GET', url);
      request.responseType = 'blob';
      // When the request loads, check whether it was successful
      request.onload = function() {
        if (request.status === 200) {
        // If successful, resolve the promise by passing back the request response
          resolve.call(null, request.response);
        } else {
        // If it fails, reject the promise with a error message
          reject.call(null, Error('Image didn\'t load successfully; error code:' + request.statusText));
        }
      };
      request.onerror = function() {
      // Also deal with the case when the entire request fails to begin with
      // This is probably a network error, so reject the promise with an appropriate message
          reject.call(null, Error('There was a network error.'));
      };
      // Send the request
      request.send();
    });
  }
  // Get a reference to the body element, and create a new image object
  var body = document.querySelector('body');
  var myImage = new Image();
  // Call the function with the URL we want to load, but then chain the
  // promise then() method on to the end of it. This contains two callbacks
  imgLoad('myLittleVader.jpg').then(function(response) {
    // The first runs when the promise resolves, with the request.response
    // specified within the resolve() method.
    var imageURL = window.URL.createObjectURL(response);
    myImage.src = imageURL;
    body.appendChild(myImage);
    // The second runs when the promise
    // is rejected, and logs the Error specified with the reject() method.
  }, function(Error) {
    console.log(Error);
  });

四、Promise使用方法小结

第一步

  1. return new Promise((resolve, reject) =>{...})
  2. 任务成功就调用 resolve.call(null, result)
  3. 任务失败就调用 reject.call(null, errorMessage)
  4. resolve和reject会再去调用成功和失败函数

第二步

  1. 使用.then(success, fail) 传入成功和失败函数

    a. success.call(null, result)  参数来自resolve

    b.fail.call(null, errorMessage)  参数来自reject

 
 
 
posted @ 2021-03-29 17:12  蛰鸣  阅读(76)  评论(0编辑  收藏  举报