简体   繁体   中英

Javascript: In promises what is the purpose of resolve and reject?

As I understand it, resolve and reject are specified in the callback provided to the promise constructor and invoked within the callback. But resolve and reject (I think) always do the same thing, so why do they even have to be specified?

I mean resolve seems to always resolve and reject always reject -- is there a way to pass in a function instead of resolve that does something else?

How can that be? I did not define foo at all?? I probably am not understanding something about javascript beyond promises. code snippet where i changed resolve to foo<\/a>

When you create a JS Promise, you expect some task to happen asynchronously. It is possible, that this task can succeed or fail. The success and failure are defined based on what the task is.

When you create a new Promise, you as the creator must specify what to do when the task is successful or is a failure. To communicate the same to the consumer of the promise resolve/reject come handy.

So when the consumer uses a then to check the output of the promise. what ever is returned by resolve is given to the consumer.

When the consumer uses a catch to check the output of the promise. whatever is returned by the reject is given to the consumer.

import {Promise} from 'es6-promise'


const foo = true;
const bar = new Promise((resolve, reject) => {
    if (foo) {
        resolve(4);
    } else {
        reject(2);
    }
})
bar.then((value) => console.log(value)).catch((value) => console.log(value));

you can run the above sample by changing the value of foo to true/false and see for yourself what the output is.

I assume you are referring to the then() function which takes two callbacks, one when the promise is resolved and one when it is resolved. The pattern often looks like this:

myPromise.then(result => {
        // do something here
    },
    error => {
    }
);

If the promise is resolved everything went as expected and the first callback should proceed as normal. If the promise is rejected the second callback should perform error handling, possibly displaying an appropriate message to the user. These never do the same thing.

If you have logic that should always occur, whether there is an error or not, you should chain another call to then() :

myPromise.then(result => {
        // do something here
    },
    error => {
        // do something here
    }
).then(result => {
        // do something here
    }
);

This is conceptually the same as try...catch...finally from many programming languages.

Resolve and reject do not "do the same thing".

When you resolve a promise you are saying "this is the successful response of this promise".

When you reject a promise you are saying "this promise failed because...".

For example:

Imagine in the following examples accountApiRequest() actually does an API request to fetch an account. If there is no account it will most likely return null or throw an exception.

When a promise is successful you will resolve it. When a promise is not successful it will be rejected .

Successful promise

 function accountApiRequest() { return { id: 1234, username: 'Jim', } } function getAccount() { return new Promise(function(resolve, reject) { account = accountApiRequest() if (!account) { return reject('Unable to fetch account') } return resolve(account) }); } getAccount().then(console.log).catch(console.log)

Failed promise

 function accountApiRequest() { return null } function getAccount() { return new Promise(function(resolve, reject) { account = accountApiRequest() if (!account) { return reject('Unable to fetch account') } return resolve(account) }); } getAccount().then(console.log).catch(console.log)

In the Promise constructor we have a callback which takes the resolve and reject methods as its arguments. After a Promise is created using the constructor a Promise can have three states:

  1. Pending
  2. Resolved
  3. Rejected

When a promise is resolved then the callback which is passed in the then() method is called. If the promise is rejected the callback which is passed in the catch() method is called. For example:

 const prom = new Promise((resolve, reject) => { setTimeout(() => { if(Math.random() > 0.5) { resolve('resolved'); } else { reject('rejected'); } } , 2000) }); prom.then((val) => console.log('succes: ' + val)) .catch((val) => console.log('fail: ' + val))

In our example the resolve or reject is called in a setTimeout , therefore the status of the promise is the first 2 seconds pending . After the setTimeout is expired the Promise is either resolved or rejected based on the value of Math.random() . Then either the then or the catch callback is executed to handle the result of the promise.

  • When the promise is rejected the callback passed in the catch method is called
  • When the promise is resolved the callback passed in the then method is called

I have spent a ton of time trying to figure this out. Unfortunately, for anyone well versed with JS syntax, won't really understand the question...

For me, it was clear, after unraveling the concise JS syntactic sugar:

function promise_executor(resolve_callback_provided_by_promise_instance, reject_callback_provided_by_promise_instance) {
    if (<some_condition>) {
        // success
        var response='bla';
        resolve_callback_provided_by_promise_instance(response);
    } else {
        // fail
        var error=new Error('failed');
        reject_callback_provided_by_promise_instance(error);
    }
}

var promise_instance = new Promise(promise_executor);

So the reject and resolve are just random names for callbacks that the promise instance will call.

They have proper interfaces, like both will take 1 param of type object. That param will be passed to either the Promise.then() or the Promise.catch().

resolve

reject


Then, when you use them, it is like this:

function success_callback(param_from_resolve) {
    console.log('success() ', param_from_resolve);
}

function fail_callback(param_from_reject) {
    console.log('fail(): ', param_from_reject);
}

promise_instance
.then(success_callback)   // this will be the var 'resolve' from above
.catch(fail_callback);    // this will be the var 'error' from above

The whole code flow is like this:

<at some point, your promise_executor() code is called with 2 functions, as parameters>

// obviously, the promise_executor() function has its own name in the Promise object
promise_executor(Promise.reject, Promise.resolve);

< promise_executor() will -hopefully- call either the resolve or the reject callback, which will in turn trigger either the callback of then() or catch() >

<say we have then() >

<the Promise code will take the response param from resolve_callback_provided_by_promise_instance(response) and give it to the callback from then() >

param_from_resolve(response)

It will go down something like this (THIS IS NOT what actually happens, as in reality, the micro-queue, the eventloop, etc. gets involved - this is a linearized version of the gist of what is happening):

What you see:

var promise = new Promise(promise_executor);

What is executed:

function Promise.constructor(exec_callback_fnc) {
    var this = object();
    this.exec_callback_fnc = exec_callback_fnc; // this is "promise_executor"
    return this;
}

What you see:

// at some point in "this.exec_callback_fnc":
resolve_callback_provided_by_promise_instance(response)

What is executed:

function promise_instance.resolve(param) {
    this.param_from_resolve = param;
    promise_instance.resolved = true;
}

What you see:

promise_instance
.then(success_callback)

What is executed:

promise_instance.exec_callback_fnc(promise_instance.resolve, promise_instance.reject);

if (promise_instance.resolved) {

    function promise_instance.then(callback_fnc) {
        callback_fnc(this.param_from_resolve);  // this is "success_callback"
    }
}

Finally, let's see, how the syntax makes this whole thing more concise:

function promise_executor(resolve_callback_provided_by_promise_instance,
                          reject_callback_provided_by_promise_instance) {
    if (<some_condition>) {
        // success
        var response='bla';
        resolve_callback_provided_by_promise_instance(response);
    } else {
        // fail
        var error=new Error('failed');
        reject_callback_provided_by_promise_instance(error);
    }
}

var promise_instance = new Promise(promise_executor);

function success_callback(param_from_resolve) {
    console.log('success() ', param_from_resolve);
}

function fail_callback(param_from_reject) {
    console.log('fail(): ', param_from_reject);
}

promise_instance
.then(success_callback)
.catch(fail_callback);

Will become:

new Promise((resolve_callback_provided_by_promise_instance,
             reject_callback_provided_by_promise_instance) => {
    if (<some_condition>) {
        // success
        var response='bla';
        resolve_callback_provided_by_promise_instance(response);
    } else {
        // fail
        var error=new Error('failed');
        reject_callback_provided_by_promise_instance(error);
    }})
// "response" -> "param_from_resolve"
.then((param_from_resolve) => { console.log('success() ', param_from_resolve); })
 // "error" -> "param_from_reject"
.catch((param_from_reject) => { console.log('fail(): ', param_from_reject); });

Both resolve and reject essentially do the same thing. They are callbacks. But, they will help in handling errors or any other logic you need to run to determine a pass/fail.

Example: Reject will end up in your catch. Resolve ends up in your then (resolve)

 function myPromise(rejectOrResolve) { return new Promise( (resolve, reject) => { if (rejectOrResolve) { resolve(); } else { reject(); } }); } // Resolved (Success) myPromise(true).then( t => { console.log('resolve'); }).catch( e => { console.log('reject'); }); // Rejected (Error) myPromise(false).then( t => { console.log('resolve'); }).catch( e => { console.log('reject'); }); 

I had the same question when I read about Promises. And I came to understanding that you don't need to define resolve and reject functions by yourself (they will be ignored and standard resolve/reject functions will be called anyway): I think of them as special functions which let you indicate whether to resolve or reject the promise by calling one of them; and what value to return in each case by passing arguments to these functions. It doesn't matter how you name them in promise constructor - first argument is resolve function and the second - reject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM