MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Promise.prototype.then()

翻譯不完整。請協助 翻譯此英文文件

then() 方法會回傳一個新的 Promise 物件。其兩個參數分別為:Promise 物件在成功及失敗情形下的回呼函式。

Note: If both arguments are omitted, or are provided non-functions, a new Promise is created with no additional handlers, simply adopting the final state of the Promise that then is called on. If the first argument is omitted or provided a non-function, the new Promise that is created simply adopts the fulfillment state of the Promise that then is called on (if it becomes fulfilled). If the second argument is omitted or provided a non-function, the new Promise that is created simply adopts the rejection state of the Promise that then is called on (if it becomes rejected).

語法

p.then(onFulfilled[, onRejected]);

p.then(function(value) {
  // fulfillment
}, function(reason) {
  // rejection
});

參數

onFulfilled
A Function called when the Promise is fulfilled. This function has one argument, the fulfillment value.
onRejected 選擇性
A Function called when the Promise is rejected. This function has one argument, the rejection reason.

回傳值

A Promise which rejects or resolves with the value returned by the input function onFulfilled or onRejected.

It returns a rejected Promise if

  • the input function throws an error, or
  • the input function returns a rejected Promise.

A resolved Promise is returned if

  • the input function returns a value, or
  • the input function returns a resolved Promise.

描述

As the then and Promise.prototype.catch() methods return promises, they can be chained — an operation called composition.

範例

Using the then method

var p1 = new Promise( (resolve, reject) => {
  resolve('Success!');
  // or
  // reject ("Error!");
} );

p1.then( value => {
  console.log(value); // Success!
}, reason => {
  console.log(reason); // Error!
} );

Chaining

The then method returns a Promise which allows for method chaining.

You can pass a lambda to then and if it returns a promise, an equivalent Promise will be exposed to the subsequent then in the method chain. The below snippet simulates asynchronous code with the setTimout function.

Promise.resolve('foo')
  // 1. Receive "foo" concatenate "bar" to it and resolve that to the next then
  .then(function(string) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        string += 'bar';
        resolve(string);
      }, 1);
    });
  })
  // 2. receive "foobar", register a callback function to work on that string
  // and print it to the console, but not before return the unworked on
  // string to the next then
  .then(function(string) {
    setTimeout(function() {
      string += 'baz';
      console.log(string);
    }, 1)
    return string;
  })
  // 3. print helpful messages about how the code in this section will be run
  // before string is actually processed by the mocked asynchronous code in the
  // prior then block.  
  .then(function(string) {
    console.log("Last Then:  oops... didn't bother to instantiate and return " +
                "a promise in the prior then so the sequence may be a bit " +
                "surprising");

    // Note that `string` will not have the 'baz' bit of it at this point. This 
    // is because we mocked that to happen asynchronously with a setTimeout function
    console.log(string);
  });

When a value is simply returned from within a then lambda, it will effectively return Promise.resolve(<value returned by whichever handler was called>).

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

p2.then(function(value) {
  console.log(value); // 1
  return value + 1;
}).then(function(value) {
  console.log(value + '- This synchronous usage is virtually pointless'); // 2- This synchronous usage is virtually pointless
});

p2.then(function(value) {
  console.log(value); // 1
});

A then call will return a rejected promise if the function throws an error or returns a rejected Promise.

Promise.resolve()
  .then( () => {
    // Makes .then() return a rejected promise
    throw 'Oh no!';
  })
  .then( () => { 
    console.log( 'Not called.' );
  }, reason => {
    console.error( 'onRejected function called: ', reason );
  });

In all other cases, a resolving Promise is returned. In the following example, the first then() will return 42 wrapped resolving Promise even though the previous Promise in the chain was rejected.

Promise.reject()
  .then( () => 99, () => 42 ) // onRejected returns 42 which is wrapped in a resolving Promise
  .then( solution => console.log( 'Resolved with ' + solution ) ); // Resolved with 42

In practice, it is often desirable to catch rejected promises rather than use then's two case syntax, as demonstrated below.

Promise.resolve()
  .then( () => {
    // Makes .then() return a rejected promise
    throw 'Oh no!';
  })
  .catch( reason => {
    console.error( 'onRejected function called: ', reason );
  })
  .then( () => {
    console.log( "I am always called even if the prior then's promise rejects" );
  });


You can also use chaining to implement one function with a Promise-based API on top of another such function.

function fetch_current_data() {
  // The fetch() API returns a Promise.  This function
  // exposes a similar API, except the fulfillment
  // value of this function's Promise has had more
  // work done on it.
  return fetch('current-data.json').then((response) => {
    if (response.headers.get('content-type') != 'application/json') {
      throw new TypeError();
    }
    var j = response.json();
    // maybe do something with j
    return j; // fulfillment value given to user of
              // fetch_current_data().then()
  });
}

If onFulfilled returns a promise, the return value of then will be resolved/rejected by the promise.

function resolveLater(resolve, reject) {
  setTimeout(function () {
    resolve(10);
  }, 1000);
}
function rejectLater(resolve, reject) {
  setTimeout(function () {
    reject(20);
  }, 1000);
}

var p1 = Promise.resolve('foo');
var p2 = p1.then(function() {
  // Return promise here, that will be resolved to 10 after 1 second
  return new Promise(resolveLater);
});
p2.then(function(v) {
  console.log('resolved', v);  // "resolved", 10
}, function(e) {
  // not called
  console.log('rejected', e);
});

var p3 = p1.then(function() {
  // Return promise here, that will be rejected with 20 after 1 second
  return new Promise(rejectLater);
});
p3.then(function(v) {
  // not called
  console.log('resolved', v);
}, function(e) {
  console.log('rejected', e); // "rejected", 20
});

規範

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Promise.prototype.then' in that specification.
Standard Initial definition in an ECMA standard.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Promise.prototype.then' in that specification.
Draft

瀏覽器相容性

Feature Chrome Edge Firefox Internet Explorer Opera Safari Servo
Basic Support32.0(Yes)29.0No support197.1No support
Feature Android Chrome for Android Edge Mobile Firefox for Android IE Mobile Opera Mobile Safari Mobile
Basic Support4.4.432.0(Yes)29No support(Yes)8.0

參見

文件標籤與貢獻者

 此頁面的貢獻者: jackblackevo, liuderchi
 最近更新: jackblackevo,