te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Why is it possible to pass in a non-function parameter to Promise.then() without causing an error? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why is it possible to pass in a non-function parameter to Promise.then() without causing an error? - Stack Overflow

programmeradmin5浏览0评论

I have the following:

new Promise(resolve => setTimeout(resolve, 2000))
    .then(() => console.log("after 2 seconds"));

new Promise(resolve => setTimeout(resolve, 3000))
    .then(console.log("before 3 seconds (instantly)"));

which produces the following output:

> node index.js
before 3 seconds (instantly)
after 2 seconds

Promise.then() expects a onFulfilled function, but I passed in console.log("before 2 seconds (instantly)"), which is not a function. Two-part question:

  • Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?
  • Why didn't the second Promise raise an exception when I didn't pass in a function?

I have the following:

new Promise(resolve => setTimeout(resolve, 2000))
    .then(() => console.log("after 2 seconds"));

new Promise(resolve => setTimeout(resolve, 3000))
    .then(console.log("before 3 seconds (instantly)"));

which produces the following output:

> node index.js
before 3 seconds (instantly)
after 2 seconds

Promise.then() expects a onFulfilled function, but I passed in console.log("before 2 seconds (instantly)"), which is not a function. Two-part question:

  • Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?
  • Why didn't the second Promise raise an exception when I didn't pass in a function?
Share Improve this question asked Feb 7, 2017 at 16:15 neverendingqsneverendingqs 4,2763 gold badges36 silver badges58 bronze badges 2
  • "Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?" Why wouldn't it get executed instantly? Before the result of an expression can be passed as an argument, it needs to be evaluated. In this case, evaluating console.log("before 3 seconds (instantly)") results in stuff being logged to the console, followed by the undefined result being used as an argument for invoking Promise#then. – user1726343 Commented Feb 7, 2017 at 16:22
  • 1 Did my answer below answer your questions? Any ments? – rsp Commented Feb 10, 2017 at 11:02
Add a ment  | 

3 Answers 3

Reset to default 7

The code

console.log("before 3 seconds (instantly)")

is an expression, specifically a function call expression. Wherever that appears, it means the same thing, including an appearance as an argument to the .then() method of a Promise. As in any other similar language, an expression used in a function call is evaluated before the function call, so

.then(console.log("before 3 seconds (instantly)"))

results in the console.log() function being called first, with the return value then passed to .then(). That's why you see the message in the console immediately.

Passing undefined to .then() is allowed, and since that's what console.log() returns, there's no error raised.

If you want that console.log() to happen when the Promise is fulfilled, you'd wrap it in a function:

.then(function() { console.log("after 3 seconds"); })

Why is it possible to pass in a non-function parameter to Promise.then() without causing an error?

Yes. All non-function arguments should be ignored. See below.

Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?

Because in JS the arguments to functions calls are evaluated instantly (applicative order).

Why didn't the second Promise raise an exception when I didn't pass in a function?

Because console.log returns undefined and .then() with no arguments is legal (because both handlers are optional). In your example console.log() returns undefined so it is like calling .then() with no arguments.

But even if it was called with some arguments that are not functions, they would still get ignored. For example even in this example the 'ok' would still get to the console.log at the end, which may be surprising:

Promise.resolve('ok')
    .then()
    .then(false)
    .then(null)
    .then(1)
    .then('x')
    .then([1, 2, 3])
    .then({a: 1, b: 2})
    .then(console.log);

See the Promises/A+ specification, section 2.2.1 that describe the arguments to the .then() method:

2.2.1 Both onFulfilled and onRejected are optional arguments:

  • If onFulfilled is not a function, it must be ignored.
  • If onRejected is not a function, it must be ignored.

Why does console.log("before 2 seconds (instantly)") get executed right away (or at all)?

A function's parameters are evaluated before the function is called. When you do alert(1+2) you expect 1+2 to be evaluated first, and when you do alert(console.log("...")) you should likewise expect console.log("...") to be evaluated first. There's nothing special about then; it's just a regular function and its arguments are treated the same as any other function's arguments.

Why didn't the second Promise raise an exception when I didn't pass in a function?

Because console.log returns undefined, and the language specification (ECMAScript 2015) says what should happen when you call then(undefined), and it's not throwing an exception. Let's look at what it does say:

25.4.5.3.1 PerformPromiseThen ( promise, onFulfilled, onRejected, resultCapability )

The abstract operation PerformPromiseThen performs the “then” operation on promise using onFulfilled and onRejected as its settlement actions. The result is resultCapability’s promise.

  1. Assert: IsPromise(promise) is true.
  2. Assert: resultCapability is a PromiseCapability record.
  3. If IsCallable(onFulfilled) is false, then
    1. Let onFulfilled be "Identity".
  4. If IsCallable(onRejected) is false, then
    1. Let onRejected be "Thrower".
  5. Let fulfillReaction be the PromiseReaction { [[Capabilities]]: resultCapability, [[Handler]]: onFulfilled }.
  6. ...

The salient points here are (3) and (5). In (3), since onFulfilled is undefined, IsCallable(onFulfilled) is false and so onFulfilled is set to "Identity". Then, in (5), a PromiseReaction is created with the [[Handler]] onFulfulled, which we know is "Identity".

Here's what the section PromiseReaction Records says about "Identity":

If [[Handler]] is "Identity" it is equivalent to a function that simply returns its first argument.

So there you have it. Calling then(undefined) is basically the same as calling then(a => a), which is why you don't get an error.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论